/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

#include <map>
#import <JavaScriptCore/JavaScriptCore.h>
#import <WebKit/WebKit.h>
#import "BrowserChannel.h"
#import "Debug.h"
#import "GTMSystemVersion.h"
#import "NSMutableString+HtmlReplacement.h"
#import "LoadModuleMessage.h"
#import "OophmWebScriptObject.h"
#import "SessionHandler.h"
#import "AllowedConnections.h"

/*
 * This is a helper shim to bridge crash events from the core cpp code to the
 * objc plugin and UI layer.
 */
class PluginCrashHandler : public CrashHandler {
public:
  PluginCrashHandler(OophmWebScriptObject* obj) : obj(obj) {
  }
  
  virtual void crash(const char* functionName, const char* message) {
    Debug::log(Debug::Error) << "Crashing with message: "<< message << Debug::flush;
    NSString* str = [NSString stringWithFormat:@"%s\n\n%s", message, functionName];
    [obj crashWithMessage:str];
  }
  virtual bool hasCrashed();
private:
  OophmWebScriptObject* const obj;
};

@interface OophmWebScriptObject (Private)
+ (void)logAndThrowString: (NSString*)message;
- (void)addAllowedHost: (NSString*)host;
- (BOOL)hasCrashed;
- (void)connectAlertDidEnd: (NSAlert*)alert
                returnCode: (int)returnCode
               contextInfo: (void*)contextInfo;
- (BOOL)doConnectWithUrl: (NSString*) url
          withSessionKey: (NSString*) sessionKey
                withHost: (NSString*) host
              withModule: (NSString*) moduleName
   withHostedHtmlVersion: (NSString*) hostedHtmlVersion;
	
@end

// This is declared here so that we can access the category method
bool PluginCrashHandler::hasCrashed() {
  return [obj hasCrashed] ? true : false;
}

@implementation OophmWebScriptObject
+ (void)initialize {
  // Add the plugin's bundle name to the user defaults search path
  NSBundle* pluginBundle = [NSBundle bundleForClass:[OophmWebScriptObject class]];
  NSString* bundleIdentifier = [pluginBundle bundleIdentifier];
  NSUserDefaults* shared = [NSUserDefaults standardUserDefaults];
  [shared addSuiteNamed:bundleIdentifier];
}

+ (BOOL)isSelectorExcludedFromWebScript:(SEL)selector {
  if (selector == @selector(initForWebScriptWithJsniContext:)) {
    return NO;
  } else if (selector == @selector(connectWithUrl:withSessionKey:withHost:withModuleName:withHostedHtmlVersion:)) {
    return NO;
  } else if (selector == @selector(crashWithMessage:)) {
    return NO;
  }

  return YES;
}

+ (OophmWebScriptObject*)scriptObjectWithContext: (JSGlobalContextRef) context
                                     withWebView: (WebView*) webView {
  JSGlobalContextRetain(context);
  OophmWebScriptObject* obj = [[[OophmWebScriptObject alloc] init] autorelease];
  obj->_contextRef = context;
  obj->_webView = [webView retain];
  return obj;
}

+ (NSString*)webScriptNameForSelector: (SEL)selector {
  if (selector == @selector(initForWebScriptWithJsniContext:)) {
    return @"init";
  } else if (selector == @selector(connectWithUrl:withSessionKey:withHost:withModuleName:withHostedHtmlVersion:)) {
    return @"connect";
  } else if (selector == @selector(crashWithMessage:)) {
    return @"crash";
  }
  return nil;
}

// Simply return true to indicate the plugin was successfully loaded and
// reachable.
- (BOOL)initForWebScriptWithJsniContext: (WebScriptObject*) jsniContext {
  return YES;
}

- (BOOL)connectWithUrl: (NSString*) url
        withSessionKey: (NSString*) sessionKey
              withHost: (NSString*) host
        withModuleName: (NSString*) moduleName
 withHostedHtmlVersion: (NSString*) hostedHtmlVersion {

  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];

  // See if authentication has been bypassed
  if ([defaults boolForKey:@"allowAll"]) {
    return [self doConnectWithUrl:url withSessionKey:sessionKey withHost:host
        withModule:moduleName withHostedHtmlVersion:hostedHtmlVersion];
  }
  
  // TODO(jat): do this only once, refactor to a separate method
  NSArray* allowedHosts = [defaults arrayForKey:@"allowedHosts"];
  if (allowedHosts != nil) {
    AllowedConnections::clearRules();
    int n = [allowedHosts count];
    for (int i = 0; i < n; ++i) {
      NSString* entry = [allowedHosts objectAtIndex:i];
      std::string hostName = [entry UTF8String];
      int len = hostName.length();
      bool exclude = false;
      if (len > 0) {
        if (len > 1 && hostName[0] == '!') {
          exclude = true;
          hostName = hostName.substr(1);
        }
        AllowedConnections::addRule(hostName, exclude);
      }
    }
  }

  const std::string urlStr = [url UTF8String];
  bool allowed = false;
  if (AllowedConnections::matchesRule(urlStr, &allowed)) {
    if (allowed) {
      return [self doConnectWithUrl:url withSessionKey:sessionKey withHost:host
          withModule:moduleName withHostedHtmlVersion:hostedHtmlVersion];
    } else {
      return YES;
    }
  }

  // Otherwise, bring up an alert dialog
  // TODO(jat): add an include/exclude option, currently treat as only include
  NSAlert* alert = [NSAlert alertWithMessageText:@"Initiate development mode session"
                                   defaultButton:@"Deny"
                                 alternateButton:nil
                                     otherButton:@"Allow"
                       informativeTextWithFormat:@"The current web-page would like to initiate a development-mode connection to %@", host];
  
  if ([alert respondsToSelector:@selector(setShowsSuppressionButton:)]) {
    [alert setShowsSuppressionButton:YES];
    [[alert suppressionButton] setTitle:@"Remember this decision for this server"];
  } else {
    [[alert addButtonWithTitle:@"Always allow"] setTag:NSAlertAlternateReturn];
  }
  
  NSBundle* bundle = [NSBundle bundleForClass:[OophmWebScriptObject class]];
	NSArray* contextArray = [[NSArray arrayWithObjects:[url retain],
      [sessionKey retain], [host retain], [moduleName retain],
      [hostedHtmlVersion retain], nil] retain];
  NSString* imagePath = [bundle pathForImageResource:@"gwtlogo"];
  if (imagePath != nil) {
    NSImage* img = [[[NSImage alloc] initByReferencingFile:imagePath] autorelease];
    [alert setIcon:img];
  }
  
  [alert beginSheetModalForWindow:[_webView hostWindow]
                    modalDelegate:self
                   didEndSelector:@selector(connectAlertDidEnd:returnCode:contextInfo:)
                      contextInfo:contextArray];
  return YES;
}

- (void)crashWithMessage: (NSString*)message {
  if (self->_hasCrashed) {
    return;
  }
  self->_hasCrashed = YES;
  
#ifdef GWT_DEBUGDISABLE
  // We'll call out to the JS support function
  JSGlobalContextRef contextRef = self->_contextRef;
  JSStringRef disconnectedName = JSStringCreateWithUTF8CString("__gwt_disconnected");
  JSValueRef disconnected = JSObjectGetProperty(contextRef, JSContextGetGlobalObject(contextRef), disconnectedName, NULL);
  JSStringRelease(disconnectedName);
  
  if (JSValueIsObject(contextRef, disconnected)) {
    // Found hosted.html's crash support
    JSObjectRef disconnectedFunction = JSValueToObject(contextRef, disconnected, NULL);
    JSValueRef exception = NULL;
    JSObjectCallAsFunction(contextRef, disconnectedFunction, JSContextGetGlobalObject(contextRef), 0, NULL, &exception);
    if (!exception) {
      // Couldn't invoke the crash handler.
      return;
    }
  }
#endif //GWT_DEBUGDISABLE

  // Use a simple crash page built into the bundle
  NSBundle* oophmBundle = [NSBundle bundleForClass:[self class]];
  NSString* path = [oophmBundle pathForResource:@"crash" ofType:@"html"];
  NSMutableString* crashPage = [NSMutableString stringWithContentsOfFile:path];
  [crashPage replacePattern:@"__MESSAGE__" withStringLiteral:message];
  
  long major, minor, bugFix;
  [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugFix];
  NSString* systemVersion = [NSString stringWithFormat:@"%i.%i.%i", major, minor, bugFix];
  [crashPage replacePattern:@"__SYSTEM_VERSION__" withStringLiteral:systemVersion];
  
  NSString* ua = [_webView userAgentForURL:[NSURL URLWithString:@"about:blank"]];
  [crashPage replacePattern:@"__USER_AGENT__" withStringLiteral:ua];
  
  [crashPage replacePattern:@"__DATE__"
          withStringLiteral:[NSString stringWithUTF8String:__DATE__]];
  [crashPage replacePattern:@"__TIME__"
          withStringLiteral:[NSString stringWithUTF8String:__TIME__]];  

  NSURL* currentUrl = [[[[_webView mainFrame] dataSource] response] URL];

  [[_webView mainFrame] loadAlternateHTMLString:crashPage
                                        baseURL:[NSURL fileURLWithPath:path]
                              forUnreachableURL:currentUrl];
}

- (void)dealloc {
  [_webView release];  
  delete _crashHandler;
  [super dealloc];
}

- (void)finalizeForWebScript {
  Debug::log(Debug::Info) << "Finalizing OophmWebScriptObject" << Debug::flush;
  
  // Free memory
  delete _sessionHandler;
  
  if (_hostChannel) {
    _hostChannel->disconnectFromHost();
    delete _hostChannel;
    _hostChannel = NULL;
  }

  if (_contextRef) {
    JSGlobalContextRelease(_contextRef);
    _contextRef = NULL;
  }
}
@end

@implementation OophmWebScriptObject (Private)
+ (void)logAndThrowString:(NSString*)message {
  Debug::log(Debug::Info) << "Throwing exception from WSO: " << message << Debug::flush;
  [WebScriptObject throwException:message];
}

- (void)addAllowedHost:(NSString*)host {
  /*
   * This is more complicated than usual because we're not using the
   * application's default persestent domain.  Instead, we use a plugin-specific
   * domain.
   */
  NSBundle* pluginBundle = [NSBundle bundleForClass:[OophmWebScriptObject class]];
  NSString* bundleIdentifier = [pluginBundle bundleIdentifier];
  
  NSUserDefaults* shared = [NSUserDefaults standardUserDefaults];
  NSDictionary* pluginDict = [shared persistentDomainForName:bundleIdentifier];
  NSArray* allowedHosts = [pluginDict objectForKey:@"allowedHosts"];
  
  NSMutableArray* mutableHosts = [NSMutableArray arrayWithArray:allowedHosts];
  NSMutableDictionary* mutableDict = [NSMutableDictionary dictionaryWithDictionary:pluginDict];
  [mutableHosts addObject:host];
  [mutableDict setObject:mutableHosts forKey:@"allowedHosts"];
  [shared setPersistentDomain:mutableDict forName:bundleIdentifier];
  [shared synchronize];
}

- (BOOL)hasCrashed{
  return self->_hasCrashed;
}

- (void)connectAlertDidEnd:(NSAlert *)alert
                returnCode:(int)returnCode
               contextInfo:(void *)contextInfo {
  NSArray* contextArray = (NSArray*) contextInfo;
  NSString* url = [[contextArray objectAtIndex:0] autorelease];
  NSString* sessionKey = [[contextArray objectAtIndex:1] autorelease];
  NSString* host = [[contextArray objectAtIndex:2] autorelease];
  NSString* moduleName = [[contextArray objectAtIndex:3] autorelease];
  NSString* hostedHtmlVersion = [[contextArray objectAtIndex:4] autorelease];
  [contextArray release];
  
  if (returnCode == NSAlertDefaultReturn) {
    return;
  } else if (returnCode == NSAlertAlternateReturn ||
      [alert respondsToSelector:@selector(suppressionButton)] &&
      [[alert suppressionButton] state] == NSOnState) {
    // TODO(jat): simplify, handle errors
    // Get the host part of the URL and store that
    NSString* server = [[[[[[url componentsSeparatedByString:@"://"]
        objectAtIndex:1] componentsSeparatedByString:@"/"] objectAtIndex:0]
        componentsSeparatedByString:@":"] objectAtIndex:0];
    [self addAllowedHost:server];
  }

  [self doConnectWithUrl:url withSessionKey:sessionKey withHost:host
      withModule:moduleName withHostedHtmlVersion:hostedHtmlVersion];
}

- (BOOL)doConnectWithUrl: (NSString*) url
          withSessionKey: (NSString*) sessionKey
                withHost: (NSString*) host
              withModule: (NSString*) moduleName
   withHostedHtmlVersion: (NSString*) hostedHtmlVersion {
  Debug::log(Debug::Debugging) << "connect : " << [host UTF8String] << " " <<
      [moduleName UTF8String] << Debug::flush;
  
  if (_hostChannel != NULL) {
    [OophmWebScriptObject logAndThrowString:@"Already connected"];
    return NO;
  }
  
  NSArray *parts = [host componentsSeparatedByString:@":"];
  if ([parts count] != 2) {
    [OophmWebScriptObject logAndThrowString:
     [NSString stringWithFormat:@"Incorrect format for host string %i",
      [parts count]]];
    return NO;
  }
  
  NSString *hostPart = [parts objectAtIndex:0];
  NSString *portPart = [parts objectAtIndex:1];
  
  Debug::log(Debug::Debugging) << "Extracted host: " << [hostPart UTF8String] <<
      " and port: " << [portPart UTF8String] << Debug::flush;
  
  char *hostAsChars = const_cast<char*>([hostPart UTF8String]);
  unsigned portAsInt = [portPart intValue];
  
  _hostChannel = new HostChannel();
  if (!_hostChannel->connectToHost(hostAsChars, portAsInt)) {
    [OophmWebScriptObject logAndThrowString:@"HostChannel failed to connect"];
    delete _hostChannel;
    _hostChannel = NULL;
    return NO;
  }
  
  _crashHandler = new PluginCrashHandler(self);
  _sessionHandler = new WebScriptSessionHandler(_hostChannel, _contextRef, _crashHandler);

  std::string hostedHtmlVersionStr([hostedHtmlVersion UTF8String]);
  // TODO: add support for a range of protocol versions when more are added.
  if (!_hostChannel->init(_sessionHandler, BROWSERCHANNEL_PROTOCOL_VERSION,
      BROWSERCHANNEL_PROTOCOL_VERSION, hostedHtmlVersionStr)) {
    [OophmWebScriptObject logAndThrowString:@"HostChannel failed to initialize"];
    _hostChannel->disconnectFromHost();
    delete _hostChannel;
    _hostChannel = NULL;
    return NO;
  }

  const std::string urlStr = [url UTF8String];
  // TODO(jat): add support for tab identity
  const std::string tabKeyStr = "";
  const std::string sessionKeyStr = [sessionKey UTF8String];
  const std::string moduleNameStr = [moduleName UTF8String];
    
  if (!LoadModuleMessage::send(*_hostChannel, urlStr, tabKeyStr, 
                               sessionKeyStr, moduleNameStr,
                               "Safari DMP", _sessionHandler)) {
    _hostChannel->disconnectFromHost();
    delete _hostChannel;
    _hostChannel = NULL;
    [OophmWebScriptObject logAndThrowString:@"Unable to load module"];
    return NO;
  }  
  
  return YES;
}
@end
