/*
**  Document.m
**
**  Copyright (c) 2003
**
**  Author: Yen-Ju Chen <yjchenx@hotmail.com>
**
**  This program is free software; you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation; either version 2 of the License, or
**  (at your option) any later version.
**
**  This program is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with this program; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "Document.h"
#include "Utilities.h"
#include "ToolbarView.h"
#include "FindManager.h"
#include "Inspector.h"
#include "MethodViewer.h"
#include "ScriptManager.h"
#include <CodeEditorView/CodeEditorView.h>
#include <CodeEditorView/CEView+Inspector.h>
#include <AppKit/AppKit.h>

@interface Document (CodeEditorPrivate)
/* NSScrollView is autoreleased !! */
- (NSScrollView *) _scrollViewWithCodeEditorView: (NSRect) frame;
@end

@implementation Document (CodeEditorPrivate)
- (NSScrollView *) _scrollViewWithCodeEditorView: (NSRect) frame
{
  NSScrollView *scrollView;
  CodeEditorView *ceView;
  Class CEViewClass = CodeEditorViewClass();

  NSAssert(CEViewClass, @"No CodeEditorViewClass installed");

  scrollView = [[NSScrollView alloc] initWithFrame: frame];
  [scrollView setBorderType: NSBezelBorder];
  [scrollView setHasHorizontalScroller: YES];
  [scrollView setHasVerticalScroller: YES];
  [scrollView setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];

  [[scrollView contentView] setAutoresizesSubviews:YES];

  frame = [[scrollView contentView] bounds];
  ceView = [[CEViewClass alloc] initWithFrame: frame];
  [ceView setMinSize: NSMakeSize(0,0)];
  [ceView setMaxSize: NSMakeSize(1e7, 1e7)];
  [ceView setRichText: NO];
  [ceView setSelectable: YES];
  [ceView setVerticallyResizable: YES];
  [ceView setHorizontallyResizable: YES];
  [ceView setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];

  [scrollView setDocumentView: ceView];
  RELEASE(ceView);
  return AUTORELEASE(scrollView);
}
@end

@implementation Document

/* Document */
- (void) revertDocumentToSaved: (id) sender
{
  if ([self fileName])
    {
      NSString *str = [NSString stringWithContentsOfFile: [self fileName]];

      if (str)
        {
          [currentCEView setString: str];
          [currentCEView setSelectedRange: NSMakeRange(0,0)];
        }

      /* Can use notification */
      [[Inspector sharedInspector] setCodeEditorView: currentCEView];
      [[FindManager sharedFindManager] setCodeEditorView: currentCEView];
      [[MethodViewer sharedMethodViewer] setCodeEditorView: currentCEView];
      [[ScriptManager sharedScriptManager] setCodeEditorView: currentCEView];
    }
}

- (NSData *)dataRepresentationOfType:(NSString *)type
{
  return [[currentCEView string] dataUsingEncoding: [NSString defaultCStringEncoding]];
}

- (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)type
{
  string = [[NSString alloc] initWithData: data
                             encoding: [NSString defaultCStringEncoding]];  
  if (string)
    return YES;
  else
    return NO;
}

- (CodeEditorView *) currentCodeEditorView
{
  return currentCEView;
}

/* Window Delegate */
- (BOOL) windowShouldClose: (NSNotification *) not
{
  int result;
  if ([currentCEView isDocumentEdited])
    {
      result = NSRunAlertPanel(@"Unsaved document",
                               @"This document is edited and unsaved. "
                               @"Close it anyway ?",
                               @"No", @"Save and close", @"Yes", nil);
      switch(result)
        {
          case NSAlertDefaultReturn:
            return NO;
          case NSAlertAlternateReturn:
            [self saveDocument: self];
            break;
          case NSAlertOtherReturn:
            break;
        }
    }
  return YES;
}

/* Window Controller */
- (void) showFindPanel: (id) sender
{
  [[FindManager sharedFindManager] orderFrontFindPanel: sender];
}

- (void) showInspector: (id) sender
{
  [[Inspector sharedInspector] orderFrontInspectorPanel: sender];
}

- (void) showMethodViewer: (id) sender
{
  [[MethodViewer sharedMethodViewer] orderFrontMethodPanel: sender];
}

- (void) refontify: (id) sender
{
  [currentCEView fontification];
}

- (void) markCurrentBlock: (id) sender
{
  [currentCEView markBlockAroundCursor];
}

- (void) search: (id) sender
{
  BOOL result = [currentCEView searchString: [searchField stringValue]
                                   backward: NO
                            caseInsensitive: NO];
  if (result == NO)
    {
      NSBeep();
      [searchField selectText: sender];
    }
}

- (void) goto: (id) sender
{
  int line = [sender intValue];
  if (line < 1)
    {
      NSBeep();
      NSRunAlertPanel(@"Tab spaces", @"Spaces for Tab key can't less than 0",
                      @"O.K.", nil, nil);
      [sender selectText: sender];
      return;
    }
  [sender setIntValue: line];

  [currentCEView gotoLineNum: line charInLine: 0];
  [window makeFirstResponder: currentCEView];
  [window makeKeyAndOrderFront: self];
}

- (void) windowDidBecomeKey: (NSNotification *) not
{
  /* Can use notification */
  [[Inspector sharedInspector] setCodeEditorView: currentCEView];
  [[FindManager sharedFindManager] setCodeEditorView: currentCEView];
  [[MethodViewer sharedMethodViewer] setCodeEditorView: currentCEView];
  [[ScriptManager sharedScriptManager] setCodeEditorView: currentCEView];
}

- (NSString *) windowNibName
{
  return @"Window.gorm";
}

- (void) windowControllerDidLoadNib: (NSWindowController *) controller
{
  NSScrollView *scrollView;
  NSRect frame;

  [super windowControllerDidLoadNib: controller];

  window = [controller window];

  frame = [[window contentView] bounds];
  scrollView = [self _scrollViewWithCodeEditorView: frame];
  [[window contentView] addSubview: scrollView];

  ASSIGN(currentCEView, [scrollView documentView]);

  /* Files count should be 0 or 1 depending on 
   * whether newDocument: or openDocument:
   */
  if (string)
    {
      NSString *file, *path;
      [currentCEView setString: string];
      [currentCEView setLanguageName: [self fileType]];
      [currentCEView setSelectedRange: NSMakeRange(0,0)];
      file = [[self fileName] lastPathComponent];
      path = [[self fileName] stringByDeletingLastPathComponent];
      if (path)
        [window setTitle: [NSString stringWithFormat: @"%@ -- %@", file, path]];
      else
        [window setTitle: file];
    }

  [window makeFirstResponder: currentCEView];
//  [window setDelegate: self];

  /* Toolbar */
  frame = [[window contentView] bounds];

  frame = NSMakeRect(0, frame.size.height-ToolbarHeight,
                     frame.size.width, ToolbarHeight);
  toolbar = [[ToolbarView alloc] initWithFrame: frame];
  [toolbar setAutoresizingMask: NSViewMinYMargin | NSViewWidthSizable];
  searchButton = [toolbar searchButton];
  searchField = [toolbar searchField];
  gotoField = [toolbar gotoField];

  [searchButton setTarget: self];
  [searchButton setAction: @selector(search:)];
  [searchField setTarget: self];
  [searchField setAction: @selector(search:)];
  [gotoField setTarget: self];
  [gotoField setAction: @selector(goto:)];
}

- (void) showSideView: (id) sender
{
  [currentCEView showSideTextView];
}

- (void) showToolbarView: (id) sender
{
  NSRect frame, bounds;
  NSView *view = nil;
  NSArray *array = [[window contentView] subviews];

  if ([array count] == 1) // Only NSScrollView
    { 
      view = [array objectAtIndex: 0];
      RETAIN(view);
      [view removeFromSuperview];

      bounds = [[window contentView] bounds];
      frame = NSMakeRect(0, bounds.size.height-ToolbarHeight,
                         bounds.size.width, ToolbarHeight);
      [toolbar setFrame: frame];
      [[window contentView] addSubview: toolbar];
      RELEASE(toolbar);

      frame = NSMakeRect(0, 0, bounds.size.width, 
                         bounds.size.height-ToolbarHeight);
      [view setFrame: frame];
      [[window contentView] addSubview: view];
      [window makeFirstResponder: searchField];
      RELEASE(view);
    }
  else if ([array count] == 2) // Toolbar and NSScrollView
    {
      NSEnumerator *e = [array objectEnumerator];
      id object;

      while ((object = [e nextObject]))
        {
          if (([object isKindOfClass: [NSScrollView class]]) ||
              ([object isKindOfClass: [NSTabView class]]))
            {
              view = object;
            }
          RETAIN(object);
          [object removeFromSuperview];
        }
      bounds = [[window contentView] bounds];
      [view setFrame: bounds];
      [[window contentView] addSubview: view];
      [window makeFirstResponder: currentCEView];
      RELEASE(view);
    }
}

- (id) init
{
  self = [super init];
  documentController = [DocumentController sharedDocumentController];
  return self;
}

- (void) dealloc
{
//  RELEASE(toolbar); 
  RELEASE(currentCEView);
  RELEASE(string);
  [super dealloc];
}

@end
