// Copyright 2015 The Go 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 "IvyController.h"
#import "mobile/Mobile.h"

@interface IvyController ()

@end

@implementation IvyController {
    NSArray *demo_lines;
    int demo_index;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.input.delegate = self;
    self.input.autocorrectionType = UITextAutocorrectionTypeNo;
    self.input.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
    
    self.suggestionView = [[Suggestion alloc] init];
    self.suggestionView.delegate = self;
    
    self.tape.UIDelegate = self;
    self->demo_lines=NULL;
    
    [self.okButton setTitle:@"" forState:UIControlStateNormal];
    [self.okButton setHidden:TRUE];
    
    [[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(textDidChange:)
     name:UITextFieldTextDidChangeNotification
     object:self.input];
    [[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(keyboardWillShow:)
     name:UIKeyboardWillShowNotification
     object:nil];
    [[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(keyboardWillHide:)
     name:UIKeyboardWillHideNotification
     object:nil];
    
    [self.input becomeFirstResponder];
    [self clear:NULL];
}

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
    if ([textField isEqual:self.input]) {
        textField.inputAccessoryView = self.suggestionView;
        textField.autocorrectionType = UITextAutocorrectionTypeNo;
        [textField reloadInputViews];
    }
    return YES;
}

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    if ([textField isEqual:self.input]) {
        textField.inputAccessoryView = nil;
        [textField reloadInputViews];
    }
    return YES;
}

- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)str
{
    if ([str isEqualToString:@"\n"]) {
        [self enterPressed];
        return NO;
    }
    
    return YES;
}

- (void)textDidChange:(NSNotification *)notif
{
    [self.suggestionView suggestFor:self.input.text];
}

- (void)suggestionReplace:(NSString *)text
{
    self.input.text = text;
    [self.suggestionView suggestFor:text];
}

- (void)keyboardWillShow:(NSNotification *)aNotification
{
    // Move the input text field up, as the keyboard has taken some of the screen.
    NSDictionary *info = [aNotification userInfo];
    CGRect kbFrame =
    [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    NSNumber *duration =
    [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
    
    UIViewAnimationCurve keyboardTransitionAnimationCurve;
    [[info valueForKey:UIKeyboardAnimationCurveUserInfoKey]
     getValue:&keyboardTransitionAnimationCurve];
    UIViewAnimationOptions options =
    keyboardTransitionAnimationCurve | keyboardTransitionAnimationCurve << 16;
    
    [UIView animateWithDuration:duration.floatValue
                          delay:0
                        options:options
                     animations:^{
        self.bottomConstraint.constant = 0 - kbFrame.size.height;
        [self.view layoutIfNeeded];
    }
                     completion:^(BOOL finished) {
        [self scrollTapeToBottom];
    }];
}

- (void)keyboardWillHide:(NSNotification *)aNotification
{
    // Move the input text field back down.
    NSDictionary *info = [aNotification userInfo];
    
    NSNumber *duration =
    [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];

    UIViewAnimationCurve keyboardTransitionAnimationCurve;
    [[info valueForKey:UIKeyboardAnimationCurveUserInfoKey]
     getValue:&keyboardTransitionAnimationCurve];
    UIViewAnimationOptions options =
    keyboardTransitionAnimationCurve | keyboardTransitionAnimationCurve << 16;
    
    int offset = self.input.inputAccessoryView != NULL ? self.suggestionView.frame.size.height : 0;
    
    [UIView animateWithDuration:duration.floatValue
                          delay:0
                        options:options
                     animations:^{
        self.bottomConstraint.constant = 0 - offset;
        [self.view layoutIfNeeded];
    }
                     completion:^(BOOL finished) {
        [self scrollTapeToBottom];
    }];
}

- (void)enterPressed
{
    NSString *text = self.input.text;
    if ([text isEqual:@""]){
        if(self->demo_lines==NULL){
            return;
        }
        while (demo_index < self->demo_lines.count) {
            NSString *line = self->demo_lines[self->demo_index++];
            if([line hasPrefix:@"#"]) {
                [self appendTape:line tag:@"comment"];
            } else {
                self.input.text = line;
                break;
            }
        }
    } else if (self->demo_lines!=NULL && [text isEqual:@"quit"]) {
        [self unloadDemo];
    } else {
        [self appendTape:text tag:@"expr"];
        NSString *expr = [text stringByAppendingString:@"\n"];
        NSError *err;
        NSString *result = MobileEval(expr, &err);
        if (err != nil) {
            result = err.description;
        }
        result = [result
                  stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
        result =
        [result stringByReplacingOccurrencesOfString:@"<" withString:@"&lt;"];
        result =
        [result stringByReplacingOccurrencesOfString:@">" withString:@"&gt;"];
        NSMutableArray *lines =
        (NSMutableArray *)[result componentsSeparatedByString:@"\n"];
        for (NSMutableString *line in lines) {
            if ([line hasPrefix:@"#"])
                [self appendTape:line tag:@"comment"];
            else
                [self appendTape:line tag:@"result"];
        }
        self.input.text = @"";
    }
}

- (void)scrollTapeToBottom
{
    NSString *scroll = @"window.scrollBy(0, document.body.offsetHeight);";
    [self.tape evaluateJavaScript:scroll completionHandler:nil];
}

- (void)appendTape:(NSString *)text tag:(NSString *)tag
{
    NSString *injectSrc = @"appendDiv('%@','%@');";
    NSString *runToInject = [NSString stringWithFormat:injectSrc, text, tag];
    [self.tape evaluateJavaScript:runToInject completionHandler:nil];
    [self scrollTapeToBottom];
}

- (void)loadDemo
{
    [self.okButton setHidden:FALSE];
    NSString *text = DemoText();
    
    self->demo_lines = [text componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
    self->demo_index = 0;
    self.input.text = @"";
    [self enterPressed];
}
- (void)unloadDemo
{
    [self.okButton setHidden:TRUE];
    self->demo_lines=NULL;
    self.input.text = @"";
}
- (IBAction)okPressed:(id)sender {
    [self enterPressed];
}

- (IBAction)demo:(id)sender {
    if (self->demo_lines) { // demo already running
        [self enterPressed];
    } else {
        [self loadDemo];
    }
}

- (IBAction)clear:(id)sender {
    [self unloadDemo];
    NSString *string = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]
                                                            pathForResource:@"tape" ofType:@"html"] encoding:NSUTF8StringEncoding error:NULL];
    [self.tape loadHTMLString:string baseURL:NULL];
}
@end
