/* xdaliclock - a melting digital clock
 * Copyright (c) 1991-2013 Jamie Zawinski <jwz@jwz.org>
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation.  No representations are made about the suitability of this
 * software for any purpose.  It is provided "as is" without express or
 * implied warranty.
 */

#import "DaliClockWidgetView.h"

char *progname = "Dali Clock";   // digital.c wants this for error messages.


@implementation DaliClockWidgetView


+ (void)initialize;
{
  static BOOL initialized_p = NO;
  if (initialized_p)
    return;
  initialized_p = YES;

  NSUserDefaultsController *controller =
    [NSUserDefaultsController sharedUserDefaultsController];
  NSUserDefaults *defs = [controller defaults];
  [DaliClockView registerDefaults:defs];
  // Any Widget-specific preferences would go here.
  [DaliClockView setUserDefaultsController: controller];
}



/* initWithWebView is called as the Dashboard widget and its WebView
   are initialized, which is when the widget plug-in is loaded.  This
   is just an object initializer; DO NOT use the passed WebView to
   manipulate WebScriptObjects or anything in the WebView's hierarchy.
 */
- (id) initWithWebView:(WebView*)wv
{
  NSRect rect;
  rect.origin.x = 0;
  rect.origin.y = 0;
  rect.size.width = 100;
  rect.size.height = 30;
  self = [super initWithFrame:rect];
  webView = wv;

  [self setAutoDate:67];   // show date every now and then

  return self;
}

/* windowScriptObjectAvailable passes the JavaScript window object
   referring to the plug-in's parent window (in this case, the
   Dashboard widget).  We use that to register our plug-in as a var of
   the window object; This allows the plug-in to be referenced from
   JavaScript via window.<plugInName>, or just <plugInName>.
 */
- (void) windowScriptObjectAvailable:(WebScriptObject *) ws
{
  [ws setValue:self forKey:@"DaliClock"];
}

/* Prevent direct key access from JavaScript.
   Write accessor methods and expose those if necessary
 */
+ (BOOL) isKeyExcludedFromWebScript: (const char *) key
{
  return YES;
}

/* Used for convenience of WebScripting names below
 */
NSString * const kWebSelectorPrefix = @"web_";

/* This is where prefixing our JavaScript methods with web_ pays off:
   instead of a huge if/else trail to decide which methods to exclude,
   just check the selector names for kWebSelectorPrefix.
 */
+ (BOOL) isSelectorExcludedFromWebScript:(SEL)sel
{
  return !([NSStringFromSelector(sel) hasPrefix:kWebSelectorPrefix]);
}

/* Another simple implementation: take the first token of the Obj-C
 method signature and remove the web_ prefix. So web_hourStyle is
 called from JavaScript as DaliClock.hourStyle.
 */
+ (NSString *) webScriptNameForSelector:(SEL)sel
{
  NSString *ss = NSStringFromSelector(sel);

  if ([ss hasPrefix:kWebSelectorPrefix] &&
      ([ss length] > [kWebSelectorPrefix length])) {
    return [[[ss substringFromIndex:[kWebSelectorPrefix length]]
              componentsSeparatedByString: @":"]
             objectAtIndex: 0];
  }
  return nil;
}

/* JavaScript-ready methods
 */
- (id) web_hourStyle  { return [self valueForKey:@"hourStyle"];  }
- (id) web_timeStyle  { return [self valueForKey:@"timeStyle"];  }
- (id) web_dateStyle  { return [self valueForKey:@"dateStyle"];  }
- (id) web_cycleSpeed { return [self valueForKey:@"cycleSpeed"]; }
- (id) web_usesCountdownTimer {
  return [self valueForKey:@"usesCountdownTimer"];
}
- (id) web_countdownDate {
  return [self valueForKey:@"countdownDate"];
}
- (id) web_initialForegroundColor { 
  return [self valueForKey:@"initialForegroundColor"];
}
- (id) web_initialBackgroundColor {
  return [self valueForKey:@"initialBackgroundColor"];
}

- (void) web_setHourStyle: (id)arg {
  [self setValue:arg forKey:@"HourStyle"];
}
- (void) web_setTimeStyle: (id)arg {
  [self setValue:arg forKey:@"TimeStyle"];
}
- (void) web_setDateStyle: (id)arg {
  [self setValue:arg forKey:@"DateStyle"];
}
- (void) web_setCycleSpeed: (id)arg {
  [self setValue:arg forKey:@"CycleSpeed"];
}
- (void) web_setUsesCountdownTimer: (id)arg {
  [self setValue:arg forKey:@"UsesCountdownTimer"];
}
- (void) web_setCountdownDate: (id)arg {
  [self setValue:arg forKey:@"CountdownDate"];
}
- (void) web_setInitialForegroundColor: (id)arg {
  [self setValue:arg forKey:@"InitialForegroundColor"];
}
- (void) web_setInitialBackgroundColor: (id)arg {
  [self setValue:arg forKey:@"InitialBackgroundColor"];
}

- (void) web_setFrame: (WebScriptObject *)frame
{
  NSRect rect;
  rect.origin.x    = [[frame webScriptValueAtIndex:0] doubleValue];
  rect.origin.y    = [[frame webScriptValueAtIndex:1] doubleValue];
  rect.size.width  = [[frame webScriptValueAtIndex:2] doubleValue];
  rect.size.height = [[frame webScriptValueAtIndex:3] doubleValue];

  [self setFrame: rect];
  [self setHidden:YES];
  [webView addSubview:self];
}

- (void) web_show
{
  // Start all our timers if they aren't running.
  [self clockTick];
  [self colorTick];
  [self dateTick];

  [self setHidden:NO];
}

- (void) web_hide
{
  [self setHidden:YES];

  // Kill all our timers to avoid using any CPU.

/*
  if (clockTimer && [clockTimer isValid]) {
    [clockTimer invalidate];
    clockTimer = 0;
  }

  if (colorTimer && [colorTimer isValid]) {
    [colorTimer invalidate];
    colorTimer = 0;
  }

  if (dateTimer && [dateTimer isValid]) {
    [dateTimer invalidate];
    dateTimer = 0;
  }
*/
}


/* Announce our unwillingness to accept keyboard input.
 */
- (BOOL)acceptsFirstResponder
{
  return NO;
}


#if 0
- (void)setValue:(id)value forKey:(NSString *)key
{
  NSLog(@"setValue %@ = %@", key, value);
  [super setValue:value forKey:key];

  // Make sure the preferences get written right away.
  NSUserDefaultsController *ctl = [[self class] userDefaultsController];
  [ctl commitEditing];
  [ctl save:self];
}
#endif

@end
