/* 
 * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
 *
 * 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; version 2 of the
 * License.
 * 
 * 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., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#import "MFTextEntry.h"
#import "MFMForms.h"

@implementation LimitedTextFieldFormatter

- init
{
  self = [super init];
  maxLength = INT_MAX;
  return self;
}

- (void) setMaximumLength: (int) len
{
  maxLength = len;
}

- (int) maximumLength
{
  return maxLength;
}

- (NSString *) stringForObjectValue: (id) object
{
  return (NSString *) object;
}

- (BOOL) getObjectValue: (id *) object forString: (NSString *) string errorDescription: (NSString **) error
{
  *object = string;
  return YES;
}

- (BOOL) isPartialStringValid: (NSString *) partialString newEditingString: (NSString **) newString
             errorDescription: (NSString **) error
{
  if ((int) [partialString length] > maxLength)
  {
    *newString = nil;
    return NO;
  }
  
  return YES;
}

- (NSAttributedString *) attributedStringForObjectValue: (id) anObject
                                  withDefaultAttributes: (NSDictionary *) attributes
{
  return nil;
}

@end

//--------------------------------------------------------------------------------------------------

@implementation MFTextEntryImpl

- (id)initWithObject:(::mforms::TextEntry*)aEntry type:(::mforms::TextEntryType)type
{
  self= [super initWithFrame: NSMakeRect(0, 0, 30, 0)];
  if (self)
  {
    if (type == ::mforms::PasswordEntry)
    {
      NSSecureTextField *secureField= [[NSSecureTextField alloc] initWithFrame: NSMakeRect(0, 0, 30, 0)];
      [self setCell: [secureField cell]];
      [secureField release];
    }
    else if (type == ::mforms::SearchEntry || type == ::mforms::SmallSearchEntry)
    {
      NSSearchField *searchField= [[NSSearchField alloc] initWithFrame: NSMakeRect(0, 0, 30, 0)];
      [self setCell: [searchField cell]];
      if (type == ::mforms::SmallSearchEntry)
      {
        [[self cell] setControlSize: NSSmallControlSize];
        [self setFont: [NSFont systemFontOfSize: [NSFont systemFontSizeForControlSize: NSSmallControlSize]]];
      }
      [searchField release];
    }
    mOwner= aEntry;
    mOwner->set_data(self);

    [self sizeToFit];
    mMinHeight= NSHeight([self frame]);
    
    [self setDelegate: self];
    
    [[self cell] setLineBreakMode: NSLineBreakByClipping];
    [[self cell] setScrollable: YES];
    [self setSelectable: YES];
    
    LimitedTextFieldFormatter* formatter = [[LimitedTextFieldFormatter alloc] init];
    [[self cell] setFormatter: formatter];
    [formatter release];
  }
  return self;
}

- (mforms::Object*)mformsObject
{
  return mOwner;
}


- (NSSize)minimumSize
{
  NSSize size= [[self cell] cellSize];
  
  size.height= mMinHeight;
  size.width= size.height;
  
  return size;
}

- (BOOL)heightIsFixed
{
  return YES;
}

- (void)setFixedFrameSize:(NSSize)size
{
  mFixedSize = size;
  [super setFixedFrameSize: size];
}

- (NSSize)fixedFrameSize
{
  return mFixedSize;
}


/*
- (void)setFrame:(NSRect)frame
{
  float oheight= NSHeight(frame);
  if (oheight != mMinHeight)
  {
    NSLog(@"req %@", NSStringFromRect(frame));
    // limit the frame so that the height always stays at the minimum
    frame.size.height= mMinHeight;
    frame.origin.y-= round((oheight - mMinHeight) / 2);
    frame.origin.y= MAX(frame.origin.y, 0);
    NSLog(@"give %@", NSStringFromRect(frame));
  }
  [super setFrame:frame];
}*/


- (void)controlTextDidChange:(NSNotification *)aNotification
{
  mOwner->callback();
}


-(BOOL)textView:(NSTextView *)aTextView doCommandBySelector: (SEL)aSelector
{
  struct {
    SEL selector;
    mforms::TextEntryAction action;
  } events[] = {
    { @selector(insertNewline:), mforms::EntryActivate },
    { @selector(moveUp:), mforms::EntryKeyUp }, 
    { @selector(moveDown:), mforms::EntryKeyDown },
    { @selector(moveToBeginningOfDocument:), mforms::EntryCKeyUp },
    { @selector(moveToEndOfDocument:), mforms::EntryCKeyDown },
    { 0 }
  };
  
  for (int i = 0; events[i].selector != 0; i++)
  {
    if (aSelector == events[i].selector)
    {
      mOwner->action(events[i].action);
      break; // let it fall-through so that keys like Return generate normal stuff like commit changes
    }
  }
  return NO;
}
@end




static bool entry_create(::mforms::TextEntry *self, mforms::TextEntryType type)
{
  MFTextEntryImpl *entry= [[[MFTextEntryImpl alloc] initWithObject:self type:type] autorelease];
    
  return entry != nil;
}


static void entry_set_text(::mforms::TextEntry *self, const std::string &text)
{
  if ( self )
  {
    MFTextEntryImpl* entry = self->get_data();
    [entry setStringValue:wrap_nsstring(text)];
  }
}

static void entry_set_placeholder_text(::mforms::TextEntry *self, const std::string &text)
{
  if ( self )
  {
    MFTextEntryImpl* entry = self->get_data();
    [[entry cell] setPlaceholderString: wrap_nsstring(text)];
  }
}

static void entry_set_max_length(::mforms::TextEntry *self, int maxlen)
{
  if (self)
  {
    MFTextEntryImpl* entry = self->get_data();
    [[[entry cell] formatter] setMaximumLength: maxlen];
  }
}


static std::string entry_get_text(::mforms::TextEntry *self)
{
  if ( self )
  {
    MFTextEntryImpl* entry = self->get_data();
    
    if (entry)
      return [[entry stringValue] UTF8String];
  }
  return "";
}

static void entry_set_read_only(mforms::TextEntry *self, bool flag)
{
  if ( self )
  {
    MFTextEntryImpl* entry = self->get_data();
    
    [entry setEditable: flag ? NO : YES];
  }  
}


void cf_textentry_init()
{
  ::mforms::ControlFactory *f = ::mforms::ControlFactory::get_instance();
  
  f->_textentry_impl.create= &entry_create;
  f->_textentry_impl.set_text= &entry_set_text;
  f->_textentry_impl.get_text= &entry_get_text;
  f->_textentry_impl.set_max_length= &entry_set_max_length;
  f->_textentry_impl.set_read_only= &entry_set_read_only;
  f->_textentry_impl.set_placeholder_text= &entry_set_placeholder_text;
}



