// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/cocoa/first_run_dialog_controller.h"

#include "base/i18n/rtl.h"
#include "base/strings/sys_string_conversions.h"
#include "chrome/grit/branded_strings.h"
#include "chrome/grit/generated_resources.h"
#import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/l10n_util_mac.h"

namespace {

// Return the internationalized message |message_id|, with the product name
// substituted in for $1.
std::u16string String16WithProductName(int message_id) {
  return l10n_util::GetStringFUTF16(
      message_id, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
}

// Return the internationalized message |message_id|, with the product name
// substituted in for $1.
NSString* NSStringWithProductName(int message_id) {
  return l10n_util::GetNSStringF(message_id,
                                 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME));
}

// Reflows buttons. Requires them to be passed in vertical order, top down.
CGFloat VerticallyReflowButtons(NSArray<NSButton*>* buttons) {
  CGFloat localVerticalShift = 0;
  for (NSButton* button in buttons) {
    [GTMUILocalizerAndLayoutTweaker wrapButtonTitleForWidth:button];

    NSRect oldFrame = button.frame;
    [button sizeToFit];
    NSRect newFrame = button.frame;
    // -[NSControl sizeToFit], with no layout constraints, like here, will end
    // up horizontally resizing and keeping the upper left corner in place.
    // That wrecks RTL, and because all that's really needed is vertical
    // resizing, reset the horizontal size.
    newFrame.size.width = NSWidth(oldFrame);
    button.frame = newFrame;

    localVerticalShift += NSHeight(newFrame) - NSHeight(oldFrame);
    if (localVerticalShift) {
      NSPoint origin = button.frame.origin;
      origin.y -= localVerticalShift;
      [button setFrameOrigin:origin];
    }
  }
  return localVerticalShift;
}

void MoveViewsVertically(NSArray* views, CGFloat distance) {
  for (NSView* view : views) {
    NSRect frame = view.frame;
    frame.origin.y += distance;
    [view setFrame:frame];
  }
}

// Center |view| vertically within its own superview, so its horizontal
// centerline is the same as its superview's horizontal centerline.
void CenterVertically(NSView* view) {
  NSView* superview = view.superview;
  NSRect frame = view.frame;
  NSRect superframe = superview.frame;
  frame.origin.y = (NSHeight(superframe) - NSHeight(frame)) / 2.0;
  [view setFrame:frame];
}

}  // namespace

@implementation FirstRunDialogViewController {
  NSButton* __strong _defaultBrowserCheckbox;
  NSButton* __strong _statsCheckbox;

  BOOL _statsCheckboxInitiallyChecked;
}

- (instancetype)initWithStatsCheckboxInitiallyChecked:(BOOL)checked {
  if ((self = [super init])) {
    _statsCheckboxInitiallyChecked = checked;
  }
  return self;
}

- (void)loadView {
  const int kDialogWidth = 480;

  NSBox* topBox =
      [[NSBox alloc] initWithFrame:NSMakeRect(0, 137, kDialogWidth, 52)];
  topBox.boxType = NSBoxCustom;
  topBox.contentViewMargins = NSZeroSize;
  topBox.fillColor = NSColor.controlColor;
  topBox.borderWidth = 0;

  // This string starts with the app name, which is strongly LTR, so force the
  // correct layout.
  std::u16string completeInstallationString =
      String16WithProductName(IDS_FIRSTRUN_DLG_MAC_COMPLETE_INSTALLATION_LABEL);
  base::i18n::AdjustStringForLocaleDirection(&completeInstallationString);
  NSTextField* completionLabel = [NSTextField
      labelWithString:base::SysUTF16ToNSString(completeInstallationString)];
  [completionLabel setFrame:NSMakeRect(13, 25, kDialogWidth - 2 * 13, 17)];

  _defaultBrowserCheckbox = [NSButton
      checkboxWithTitle:l10n_util::GetNSString(
                            IDS_FIRSTRUN_DLG_MAC_SET_DEFAULT_BROWSER_LABEL)
                 target:nil
                 action:nil];
  [_defaultBrowserCheckbox
      setFrame:NSMakeRect(45, 107, kDialogWidth - 2 * 45, 18)];
  [_defaultBrowserCheckbox setState:NSControlStateValueOn];

  _statsCheckbox = [NSButton
      checkboxWithTitle:NSStringWithProductName(
                            IDS_FIRSTRUN_DLG_MAC_OPTIONS_SEND_USAGE_STATS_LABEL)
                 target:nil
                 action:nil];
  [_statsCheckbox setFrame:NSMakeRect(45, 82, kDialogWidth - 2 * 45, 19)];
  if (_statsCheckboxInitiallyChecked)
    [_statsCheckbox setState:NSControlStateValueOn];

  NSButton* startChromeButton =
      [NSButton buttonWithTitle:NSStringWithProductName(
                                    IDS_FIRSTRUN_DLG_MAC_START_CHROME_BUTTON)
                         target:self
                         action:@selector(ok:)];
  [startChromeButton setFrame:NSMakeRect(161, 12, 306, 32)];
  [startChromeButton setKeyEquivalent:@"\r"];

  NSBox* topSeparator =
      [[NSBox alloc] initWithFrame:NSMakeRect(0, 136, kDialogWidth, 1)];
  [topSeparator setBoxType:NSBoxSeparator];

  NSBox* bottomSeparator =
      [[NSBox alloc] initWithFrame:NSMakeRect(0, 55, kDialogWidth, 5)];
  [bottomSeparator setBoxType:NSBoxSeparator];

  [topBox addSubview:completionLabel];
  CenterVertically(completionLabel);

  self.view =
      [[NSView alloc] initWithFrame:NSMakeRect(0, 0, kDialogWidth, 190)];
  [self.view addSubview:topBox];
  [self.view addSubview:topSeparator];
  [self.view addSubview:_defaultBrowserCheckbox];
  [self.view addSubview:_statsCheckbox];
  [self.view addSubview:bottomSeparator];
  [self.view addSubview:startChromeButton];

  // Now that the content view is constructed, fix the layout. The first step is
  // to reflow the browser and stats checkbox texts, which can be quite lengthy
  // in some locales. They may wrap onto additional lines, and in doing so cause
  // the rest of the dialog to need to be rearranged.
  {
    CGFloat delta =
        VerticallyReflowButtons(@[ _defaultBrowserCheckbox, _statsCheckbox ]);
    if (delta) {
      // If reflowing the checkboxes produced a height delta, move the
      // checkboxes and the items above them in the content view upward, then
      // grow the content view to match. This has the effect of moving
      // everything visually-below the checkboxes downwards and expanding the
      // window, leaving the vertical space the checkboxes need for their text.
      MoveViewsVertically(
          @[ _defaultBrowserCheckbox, _statsCheckbox, topSeparator, topBox ],
          delta);
      NSRect frame = [self.view frame];
      frame.size.height += delta;
      self.view.autoresizesSubviews = NO;
      self.view.frame = frame;
      self.view.autoresizesSubviews = YES;
    }
  }

  // The "Start Chrome" button needs to be sized to fit the localized string
  // inside it, but it should still be at the right-most edge of the dialog, so
  // any width added or subtracted by |sizeToFit| is added to its x coord, which
  // keeps its right edge where it was.
  CGFloat oldWidth = NSWidth([startChromeButton frame]);
  [startChromeButton sizeToFit];
  NSRect frame = [startChromeButton frame];
  frame.origin.x += oldWidth - NSWidth([startChromeButton frame]);
  if (base::i18n::IsRTL())
    frame.origin.x = kDialogWidth - NSMaxX(frame);
  [startChromeButton setFrame:frame];
}

- (NSString*)windowTitle {
  return l10n_util::GetNSString(IDS_FIRST_RUN_DIALOG_WINDOW_TITLE);
}

- (BOOL)isStatsReportingEnabled {
  return [_statsCheckbox state] == NSControlStateValueOn;
}

- (BOOL)isMakeDefaultBrowserEnabled {
  return [_defaultBrowserCheckbox state] == NSControlStateValueOn;
}

- (void)ok:(id)sender {
  [self.view.window close];
  [NSApp stopModal];
}

@end
