// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library trydart.interaction_manager;

import 'dart:html';

import 'dart:convert' show
    JSON;

import 'dart:math' show
    max,
    min;

import 'package:compiler/implementation/scanner/scannerlib.dart'
  show
    EOF_TOKEN,
    StringScanner,
    Token;

import 'package:compiler/implementation/source_file.dart' show
    StringSourceFile;

import 'compilation.dart' show
    scheduleCompilation;

import 'ui.dart' show
    currentTheme,
    hackDiv,
    inputPre,
    observer,
    outputDiv;

import 'decoration.dart' show
    CodeCompletionDecoration,
    Decoration,
    DiagnosticDecoration,
    error,
    info,
    warning;

import 'editor.dart' as editor;

import 'mock.dart' as mock;

import 'settings.dart' as settings;

/**
 * UI interaction manager for the entire application.
 */
abstract class InteractionManager {
  // Design note: All UI interactions go through one instance of this
  // class. This is by design.
  //
  // Simplicity in UI is in the eye of the beholder, not the implementor. Great
  // 'natural UI' is usually achieved with substantial implementation
  // complexity that doesn't modularise well and has nasty complicated state
  // dependencies.
  //
  // In rare cases, some UI components can be independent of this state
  // machine. For example, animation and auto-save loops.

  // Implementation note: The state machine is actually implemented by
  // [InteractionContext], this class represents public event handlers.

  factory InteractionManager() => new InteractionContext();

  InteractionManager.internal();

  void onInput(Event event);

  void onKeyUp(KeyboardEvent event);

  void onMutation(List<MutationRecord> mutations, MutationObserver observer);

  void onSelectionChange(Event event);
}

/**
 * State machine for UI interactions.
 */
class InteractionContext extends InteractionManager {
  InteractionState state;

  InteractionContext()
      : super.internal() {
    state = new InitialState(this);
  }

  void onInput(Event event) => state.onInput(event);

  void onKeyUp(KeyboardEvent event) => state.onKeyUp(event);

  void onMutation(List<MutationRecord> mutations, MutationObserver observer) {
    return state.onMutation(mutations, observer);
  }

  void onSelectionChange(Event event) => state.onSelectionChange(event);
}

abstract class InteractionState implements InteractionManager {
  void onStateChanged(InteractionState previous) {
    print('State change ${previous.runtimeType} -> ${runtimeType}.');
  }
}

class InitialState extends InteractionState {
  final InteractionContext context;
  bool requestCodeCompletion = false;

  InitialState(this.context);

  void set state(InteractionState state) {
    InteractionState previous = context.state;
    if (previous != state) {
      context.state = state;
      state.onStateChanged(previous);
    }
  }

  void onInput(Event event) {
    state = new PendingInputState(context);
  }

  void onKeyUp(KeyboardEvent event) {
    if (computeHasModifier(event)) {
      print('onKeyUp (modified)');
      onModifiedKeyUp(event);
    } else {
      print('onKeyUp (unmodified)');
      onUnmodifiedKeyUp(event);
    }
  }

  void onModifiedKeyUp(KeyboardEvent event) {
  }

  void onUnmodifiedKeyUp(KeyboardEvent event) {
    switch (event.keyCode) {
      case KeyCode.ENTER: {
        event.preventDefault();
        Selection selection = window.getSelection();
        if (selection.isCollapsed && selection.anchorNode is Text) {
          Text text = selection.anchorNode;
          int offset = selection.anchorOffset;
          text.insertData(offset, '\n');
          selection.collapse(text, offset + 1);
        }
        break;
      }
    }

    // editor.scheduleRemoveCodeCompletion();

    // This is a hack to get Safari (iOS) to send mutation events on
    // contenteditable.
    // TODO(ahe): Move to onInput?
    var newDiv = new DivElement();
    hackDiv.replaceWith(newDiv);
    hackDiv = newDiv;
  }

  // TODO(ahe): This method should be cleaned up. It is too large.
  void onMutation(List<MutationRecord> mutations, MutationObserver observer) {
    print('onMutation');

    for (String query in const ['a.diagnostic>span',
                                '.dart-code-completion',
                                '.hazed-suggestion']) {
      for (Element element in inputPre.querySelectorAll(query)) {
        element.remove();
      }
    }

    // Discard clean-up mutations.
    observer.takeRecords();

    Selection selection = window.getSelection();

    while (!mutations.isEmpty) {
      for (MutationRecord record in mutations) {
        String type = record.type;
        switch (type) {

          case 'characterData':
            bool hasSelection = false;
            int offset = selection.anchorOffset;
            if (selection.isCollapsed &&
                selection.anchorNode == record.target) {
              hasSelection = true;
            }
            var parent = record.target.parentNode;
            if (parent != inputPre) {
              editor.inlineChildren(parent);
            }
            if (hasSelection) {
              selection.collapse(record.target, offset);
            }
            break;

          default:
            if (!record.addedNodes.isEmpty) {
              for (var node in record.addedNodes) {

                if (node.nodeType != Node.ELEMENT_NODE) continue;

                if (node is BRElement) {
                  if (selection.anchorNode != node) {
                    node.replaceWith(new Text('\n'));
                  }
                } else {
                  var parent = node.parentNode;
                  if (parent == null) continue;
                  var nodes = new List.from(node.nodes);
                  var style = node.getComputedStyle();
                  if (style.display != 'inline') {
                    var previous = node.previousNode;
                    if (previous is Text) {
                      previous.appendData('\n');
                    } else {
                      parent.insertBefore(new Text('\n'), node);
                    }
                  }
                  for (Node child in nodes) {
                    child.remove();
                    parent.insertBefore(child, node);
                  }
                  node.remove();
                }
              }
            }
        }
      }
      mutations = observer.takeRecords();
    }

    if (!inputPre.nodes.isEmpty && inputPre.nodes.last is Text) {
      Text text = inputPre.nodes.last;
      if (!text.text.endsWith('\n')) {
        text.appendData('\n');
      }
    }

    int offset = 0;
    int anchorOffset = 0;
    bool hasSelection = false;
    Node anchorNode = selection.anchorNode;
    // TODO(ahe): Try to share walk4 methods.
    void walk4(Node node) {
      // TODO(ahe): Use TreeWalker when that is exposed.
      // function textNodesUnder(root){
      //   var n, a=[], walk=document.createTreeWalker(
      //       root,NodeFilter.SHOW_TEXT,null,false);
      //   while(n=walk.nextNode()) a.push(n);
      //   return a;
      // }
      int type = node.nodeType;
      if (type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE) {
        CharacterData text = node;
        if (anchorNode == node) {
          hasSelection = true;
          anchorOffset = selection.anchorOffset + offset;
          return;
        }
        offset += text.length;
      }

      var child = node.firstChild;
      while (child != null) {
        walk4(child);
        if (hasSelection) return;
        child = child.nextNode;
      }
    }
    if (selection.isCollapsed) {
      walk4(inputPre);
    }

    editor.currentSource = inputPre.text;
    inputPre.nodes.clear();
    inputPre.appendText(editor.currentSource);
    if (hasSelection) {
      selection.collapse(inputPre.firstChild, anchorOffset);
    }

    editor.isMalformedInput = false;
    for (var n in new List.from(inputPre.nodes)) {
      if (n is! Text) continue;
      Text node = n;
      String text = node.text;

      Token token = tokenize(text);
      int offset = 0;
      editor.seenIdentifiers = new Set<String>.from(mock.identifiers);
      for (; token.kind != EOF_TOKEN; token = token.next) {
        Decoration decoration = editor.getDecoration(token);
        if (decoration == null) continue;
        bool hasSelection = false;
        int selectionOffset = selection.anchorOffset;

        if (selection.isCollapsed && selection.anchorNode == node) {
          hasSelection = true;
          selectionOffset = selection.anchorOffset;
        }
        int splitPoint = token.charOffset - offset;
        Text str = node.splitText(splitPoint);
        Text after = str.splitText(token.charCount);
        offset += splitPoint + token.charCount;
        inputPre.insertBefore(after, node.nextNode);
        inputPre.insertBefore(decoration.applyTo(str), after);

        if (hasSelection && selectionOffset > node.length) {
          selectionOffset -= node.length;
          if (selectionOffset > str.length) {
            selectionOffset -= str.length;
            selection.collapse(after, selectionOffset);
          } else {
            selection.collapse(str, selectionOffset);
          }
        }
        node = after;
      }
    }

    window.localStorage['currentSource'] = editor.currentSource;
    print('Saved source');

    // Discard highlighting mutations.
    observer.takeRecords();
  }

  void onSelectionChange(Event event) {
  }

  void onStateChanged(InteractionState previous) {
    super.onStateChanged(previous);
    scheduleCompilation();
  }
}

class PendingInputState extends InitialState {
  PendingInputState(InteractionContext context)
      : super(context);

  void onInput(Event event) {
    // Do nothing.
  }

  void onMutation(List<MutationRecord> mutations, MutationObserver observer) {
    super.onMutation(mutations, observer);

    InteractionState nextState = new InitialState(context);
    if (settings.enableCodeCompletion.value) {
      Element parent = editor.getElementAtSelection();
      Element ui;
      if (parent != null) {
        ui = parent.querySelector('.dart-code-completion');
        if (ui != null) {
          nextState = new CodeCompletionState(context, parent, ui);
        }
      }
    }
    state = nextState;
  }
}

class CodeCompletionState extends InitialState {
  final Element activeCompletion;
  final Element ui;
  int minWidth = 0;
  DivElement staticResults;
  SpanElement inline;
  DivElement serverResults;
  String inlineSuggestion;

  CodeCompletionState(InteractionContext context,
                      this.activeCompletion,
                      this.ui)
      : super(context);

  void onInput(Event event) {
    // Do nothing.
  }

  void onModifiedKeyUp(KeyboardEvent event) {
    // TODO(ahe): Handle DOWN (jump to server results).
  }

  void onUnmodifiedKeyUp(KeyboardEvent event) {
    switch (event.keyCode) {
      case KeyCode.DOWN:
        return moveDown(event);

      case KeyCode.UP:
        return moveUp(event);

      case KeyCode.ESC:
        event.preventDefault();
        return endCompletion();

      case KeyCode.TAB:
      case KeyCode.RIGHT:
      case KeyCode.ENTER:
        event.preventDefault();
        return endCompletion(acceptSuggestion: true);
    }
  }

  void moveDown(Event event) {
    event.preventDefault();
    move(1);
  }

  void moveUp(Event event) {
    event.preventDefault();
    move(-1);
  }

  void move(int direction) {
    Element element = editor.moveActive(direction);
    if (element == null) return;
    var text = activeCompletion.firstChild;
    String prefix = "";
    if (text is Text) prefix = text.data.trim();
    updateInlineSuggestion(prefix, element.text);
  }

  void endCompletion({bool acceptSuggestion: false}) {
    if (acceptSuggestion) {
      suggestionAccepted();
    }
    activeCompletion.classes.remove('active');
    inputPre.querySelectorAll('.hazed-suggestion').forEach((e) => e.remove());
    // The above changes create mutation records. This implicitly fire mutation
    // events that result in saving the source code in local storage.
    // TODO(ahe): Consider making this more explicit.
    state = new InitialState(context);
  }

  void suggestionAccepted() {
    if (inlineSuggestion != null) {
      Text text = new Text(inlineSuggestion);
      activeCompletion.replaceWith(text);
      window.getSelection().collapse(text, inlineSuggestion.length);
    }
  }

  void onMutation(List<MutationRecord> mutations, MutationObserver observer) {
    for (MutationRecord record in mutations) {
      if (!activeCompletion.contains(record.target)) {
        endCompletion();
        return super.onMutation(mutations, observer);
      }
    }

    var text = activeCompletion.firstChild;
    if (text is! Text) return endCompletion();
    updateSuggestions(text.data.trim());
  }

  void onStateChanged(InteractionState previous) {
    super.onStateChanged(previous);
    displayCodeCompletion();
  }

  void displayCodeCompletion() {
    Selection selection = window.getSelection();
    if (selection.anchorNode is! Text) {
      return endCompletion();
    }
    Text text = selection.anchorNode;
    if (!activeCompletion.contains(text)) {
      return endCompletion();
    }

    int anchorOffset = selection.anchorOffset;

    String prefix = text.data.substring(0, anchorOffset).trim();
    if (prefix.isEmpty) {
      return endCompletion();
    }

    num height = activeCompletion.getBoundingClientRect().height;
    activeCompletion.classes.add('active');
    ui.nodes.clear();

    inline = new SpanElement()
        ..classes.add('hazed-suggestion');
    Text rest = text.splitText(anchorOffset);
    text.parentNode.insertBefore(inline, text.nextNode);
    activeCompletion.parentNode.insertBefore(
        rest, activeCompletion.nextNode);

    staticResults = new DivElement()
        ..classes.addAll(['dart-static', 'dart-limited-height']);
    serverResults = new DivElement()
        ..style.display = 'none'
        ..classes.add('dart-server');
    ui.nodes.addAll([staticResults, serverResults]);
    ui.style.top = '${height}px';

    staticResults.nodes.add(buildCompletionEntry(prefix));

    updateSuggestions(prefix);
  }

  void updateInlineSuggestion(String prefix, String suggestion) {
    inlineSuggestion = suggestion;

    minWidth = max(minWidth, activeCompletion.getBoundingClientRect().width);

    activeCompletion.style
        ..display = 'inline-block'
        ..minWidth = '${minWidth}px';

    inline
        ..nodes.clear()
        ..appendText(suggestion.substring(prefix.length))
        ..style.display = '';

    observer.takeRecords(); // Discard mutations.
  }

  void updateSuggestions(String prefix) {
    if (prefix.isEmpty) {
      return endCompletion();
    }

    Token first = tokenize(prefix);
    for (Token token = first; token.kind != EOF_TOKEN; token = token.next) {
      String tokenInfo = token.info.value;
      if (token != first ||
          tokenInfo != 'identifier' &&
          tokenInfo != 'keyword') {
        return endCompletion();
      }
    }

    var borderHeight = 2; // 1 pixel border top & bottom.
    num height = ui.getBoundingClientRect().height - borderHeight;
    ui.style.minHeight = '${height}px';

    minWidth =
        max(minWidth, activeCompletion.getBoundingClientRect().width);

    staticResults.nodes.clear();
    serverResults.nodes.clear();

    if (inlineSuggestion != null && inlineSuggestion.startsWith(prefix)) {
      inline
          ..nodes.clear()
          ..appendText(inlineSuggestion.substring(prefix.length));
    }

    List<String> results = editor.seenIdentifiers.where(
        (String identifier) {
          return identifier != prefix && identifier.startsWith(prefix);
        }).toList(growable: false);
    results.sort();
    if (results.isEmpty) results = <String>[prefix];

    results.forEach((String completion) {
      staticResults.nodes.add(buildCompletionEntry(completion));
    });

    if (settings.enableDartMind) {
      // TODO(ahe): Move this code to its own function or class.
      String encodedArg0 = Uri.encodeComponent('"$prefix"');
      String mindQuery =
          'http://dart-mind.appspot.com/rpc'
          '?action=GetExportingPubCompletions'
          '&arg0=$encodedArg0';
      try {
        var serverWatch = new Stopwatch()..start();
        HttpRequest.getString(mindQuery).then((String responseText) {
          serverWatch.stop();
          List<String> serverSuggestions = JSON.decode(responseText);
          if (!serverSuggestions.isEmpty) {
            updateInlineSuggestion(prefix, serverSuggestions.first);
          }
          for (int i = 1; i < serverSuggestions.length; i++) {
            String completion = serverSuggestions[i];
            DivElement where = staticResults;
            int index = results.indexOf(completion);
            if (index != -1) {
              List<Element> entries =
                  document.querySelectorAll('.dart-static>.dart-entry');
              entries[index].classes.add('doubleplusgood');
            } else {
              if (results.length > 3) {
                serverResults.style.display = 'block';
                where = serverResults;
              }
              Element entry = buildCompletionEntry(completion);
              entry.classes.add('doubleplusgood');
              where.nodes.add(entry);
            }
          }
          serverResults.appendHtml(
              '<div>${serverWatch.elapsedMilliseconds}ms</div>');
          // Discard mutations.
          observer.takeRecords();
        }).catchError((error, stack) {
          window.console.dir(error);
          window.console.error('$stack');
        });
      } catch (error, stack) {
        window.console.dir(error);
        window.console.error('$stack');
      }
    }
    // Discard mutations.
    observer.takeRecords();
  }

  Element buildCompletionEntry(String completion) {
    return new DivElement()
        ..classes.add('dart-entry')
        ..appendText(completion);
  }
}

Token tokenize(String text) {
  var file = new StringSourceFile('', text);
  return new StringScanner(file, includeComments: true).tokenize();
}

bool computeHasModifier(KeyboardEvent event) {
  return
      event.getModifierState("Alt") ||
      event.getModifierState("AltGraph") ||
      event.getModifierState("CapsLock") ||
      event.getModifierState("Control") ||
      event.getModifierState("Fn") ||
      event.getModifierState("Meta") ||
      event.getModifierState("NumLock") ||
      event.getModifierState("ScrollLock") ||
      event.getModifierState("Scroll") ||
      event.getModifierState("Win") ||
      event.getModifierState("Shift") ||
      event.getModifierState("SymbolLock") ||
      event.getModifierState("OS");
}
