// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "chrome/browser/ui/cocoa/dev_tools_controller.h"

#include <algorithm>

#include <Cocoa/Cocoa.h>

#include "chrome/browser/browser_process.h"
#include "chrome/browser/debugger/devtools_window.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#import "chrome/browser/ui/cocoa/view_id_util.h"
#include "chrome/common/pref_names.h"
#include "content/browser/tab_contents/tab_contents.h"

namespace {

// Default offset of the contents splitter in pixels.
const int kDefaultContentsSplitOffset = 400;

// Never make the web part of the tab contents smaller than this (needed if the
// window is only a few pixels high).
const int kMinWebHeight = 50;

}  // end namespace


@interface DevToolsController (Private)
- (void)showDevToolsContents:(TabContents*)devToolsContents
                 withProfile:(Profile*)profile;
- (void)resizeDevToolsToNewHeight:(CGFloat)height;
@end


@implementation DevToolsController

- (id)initWithDelegate:(id<TabContentsControllerDelegate>)delegate {
  if ((self = [super init])) {
    splitView_.reset([[NSSplitView alloc] initWithFrame:NSZeroRect]);
    [splitView_ setDividerStyle:NSSplitViewDividerStyleThin];
    [splitView_ setVertical:NO];
    [splitView_ setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
    [splitView_ setDelegate:self];

    contentsController_.reset(
        [[TabContentsController alloc] initWithContents:NULL
                                               delegate:delegate]);
  }
  return self;
}

- (void)dealloc {
  [splitView_ setDelegate:nil];
  [super dealloc];
}

- (NSView*)view {
  return splitView_.get();
}

- (NSSplitView*)splitView {
  return splitView_.get();
}

- (void)updateDevToolsForTabContents:(TabContents*)contents
                         withProfile:(Profile*)profile {
  // Get current devtools content.
  TabContentsWrapper* devToolsTab = contents ?
      DevToolsWindow::GetDevToolsContents(contents) : NULL;
  TabContents* devToolsContents = devToolsTab ?
      devToolsTab->tab_contents() : NULL;

  [self showDevToolsContents:devToolsContents withProfile:profile];
}

- (void)ensureContentsVisible {
  [contentsController_ ensureContentsVisible];
}

- (void)showDevToolsContents:(TabContents*)devToolsContents
                 withProfile:(Profile*)profile {
  [contentsController_ ensureContentsSizeDoesNotChange];

  NSArray* subviews = [splitView_ subviews];
  if (devToolsContents) {
    DCHECK_GE([subviews count], 1u);

    // |devToolsView| is a TabContentsViewCocoa object, whose ViewID was
    // set to VIEW_ID_TAB_CONTAINER initially, so we need to change it to
    // VIEW_ID_DEV_TOOLS_DOCKED here.
    view_id_util::SetID(
        devToolsContents->GetNativeView(), VIEW_ID_DEV_TOOLS_DOCKED);

    CGFloat splitOffset = 0;
    if ([subviews count] == 1) {
      // Load the default split offset.
      splitOffset = profile->GetPrefs()->
          GetInteger(prefs::kDevToolsSplitLocation);
      if (splitOffset < 0) {
        // Initial load, set to default value.
        splitOffset = kDefaultContentsSplitOffset;
      }
      [splitView_ addSubview:[contentsController_ view]];
    } else {
      DCHECK_EQ([subviews count], 2u);
      // If devtools are already visible, keep the current size.
      splitOffset = NSHeight([[subviews objectAtIndex:1] frame]);
    }

    // Make sure |splitOffset| isn't too large or too small.
    splitOffset = std::max(static_cast<CGFloat>(kMinWebHeight), splitOffset);
    splitOffset =
        std::min(splitOffset, NSHeight([splitView_ frame]) - kMinWebHeight);
    DCHECK_GE(splitOffset, 0) << "kMinWebHeight needs to be smaller than "
                              << "smallest available tab contents space.";

    [self resizeDevToolsToNewHeight:splitOffset];
  } else {
    if ([subviews count] > 1) {
      NSView* oldDevToolsContentsView = [subviews objectAtIndex:1];
      // Store split offset when hiding devtools window only.
      int splitOffset = NSHeight([oldDevToolsContentsView frame]);

      profile->GetPrefs()->SetInteger(
          prefs::kDevToolsSplitLocation, splitOffset);
      [oldDevToolsContentsView removeFromSuperview];
      [splitView_ adjustSubviews];
    }
  }

  [contentsController_ changeTabContents:devToolsContents];
}

- (void)resizeDevToolsToNewHeight:(CGFloat)height {
  NSArray* subviews = [splitView_ subviews];

  // It seems as if |-setPosition:ofDividerAtIndex:| should do what's needed,
  // but I can't figure out how to use it. Manually resize web and devtools.
  // TODO(alekseys): either make setPosition:ofDividerAtIndex: work or to add a
  // category on NSSplitView to handle manual resizing.
  NSView* devToolsView = [subviews objectAtIndex:1];
  NSRect devToolsFrame = [devToolsView frame];
  devToolsFrame.size.height = height;
  [devToolsView setFrame:devToolsFrame];

  NSView* webView = [subviews objectAtIndex:0];
  NSRect webFrame = [webView frame];
  webFrame.size.height =
      NSHeight([splitView_ frame]) - ([splitView_ dividerThickness] + height);
  [webView setFrame:webFrame];

  [splitView_ adjustSubviews];
}

// NSSplitViewDelegate protocol.
- (BOOL)splitView:(NSSplitView *)splitView
    shouldAdjustSizeOfSubview:(NSView *)subview {
  // Return NO for the devTools view to indicate that it should not be resized
  // automatically. It preserves the height set by the user and also keeps
  // view height the same while changing tabs when one of the tabs shows infobar
  // and others are not.
  if ([[splitView_ subviews] indexOfObject:subview] == 1)
    return NO;
  return YES;
}

@end