// Copyright (c) 2012, 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.

part of client_live_nav;

List libraryList;
InputElement searchInput;
DivElement dropdown;

/**
 * Update the search drop down based on the current search text.
 */
updateDropDown(Event event) {
  if (libraryList == null) return;
  if (searchInput == null) return;
  if (dropdown == null) return;

  var results = <Result>[];
  String text = searchInput.value;
  if (text == currentSearchText) {
    return;
  }
  if (text.isEmpty) {
    updateResults(text, results);
    hideDropDown();
    return;
  }
  if (text.contains('.')) {
    // Search type members.
    String typeText = text.substring(0, text.indexOf('.'));
    String memberText = text.substring(text.indexOf('.') + 1);

    if (typeText.isEmpty && memberText.isEmpty) {
      // Don't search on '.'.
    } else if (typeText.isEmpty) {
      // Search text is of the form '.id' => Look up members.
      matchAllMembers(results, memberText);
    } else if (memberText.isEmpty) {
      // Search text is of the form 'Type.' => Look up members in 'Type'.
      matchAllMembersInType(results, typeText, memberText);
    } else {
      // Search text is of the form 'Type.id' => Look up member 'id' in 'Type'.
      matchMembersInType(results, text, typeText, memberText);
    }
  } else {
    // Search all entities.
    var searchText = new SearchText(text);
    for (Map<String,dynamic> library in libraryList)  {
      matchLibrary(results, searchText, library);
      matchLibraryMembers(results, searchText, library);
      matchTypes(results, searchText, library);
    }
  }
  var elements = <Element>[];
  var table = new TableElement();
  table.classes.add('drop-down-table');
  elements.add(table);

  if (results.isEmpty) {
    var row = table.insertRow(0);
    row.innerHTML = "<tr><td>No matches found for '$text'.</td></tr>";
  } else {
    results.sort(resultComparator);

    var count = 0;
    for (Result result in results) {
      result.addRow(table);
      if (++count >= 10) {
        break;
      }
    }
    if (results.length >= 10) {
      var row = table.insertRow(table.rows.length);
      row.innerHTML = '<tr><td>+ ${results.length-10} more.</td></tr>';
      results = results.getRange(0, 10);
    }
  }
  dropdown.elements = elements;
  updateResults(text, results);
  showDropDown();
}

void matchAllMembers(List<Result> results, String memberText) {
  var searchText = new SearchText(memberText);
  for (Map<String,dynamic> library in libraryList)  {
    String libraryName = library[NAME];
    if (library.containsKey(TYPES)) {
      for (Map<String,dynamic> type in library[TYPES]) {
        String typeName = type[NAME];
        if (type.containsKey(MEMBERS)) {
          for (Map<String,dynamic> member in type[MEMBERS]) {
            StringMatch memberMatch = obtainMatch(searchText, member[NAME]);
            if (memberMatch != null) {
              results.add(new Result(memberMatch, member[KIND],
                  getTypeMemberUrl(libraryName, typeName, member),
                  library: libraryName, type: typeName, args: type[ARGS],
                  noargs: member[NO_PARAMS]));
            }
          }
        }
      }
    }
  }
}

void matchAllMembersInType(List<Result> results,
                           String typeText, String memberText) {
  var searchText = new SearchText(typeText);
  var emptyText = new SearchText(memberText);
  for (Map<String,dynamic> library in libraryList)  {
    String libraryName = library[NAME];
    if (library.containsKey(TYPES)) {
      for (Map<String,dynamic> type in library[TYPES]) {
        String typeName = type[NAME];
        StringMatch typeMatch = obtainMatch(searchText, typeName);
        if (typeMatch != null) {
          if (type.containsKey(MEMBERS)) {
            for (Map<String,dynamic> member in type[MEMBERS]) {
              StringMatch memberMatch = obtainMatch(emptyText,
                  member[NAME]);
              results.add(new Result(memberMatch, member[KIND],
                  getTypeMemberUrl(libraryName, typeName, member),
                  library: libraryName, prefix: typeMatch,
                  noargs: member[NO_PARAMS]));
            }
          }
        }
      }
    }
  }
}

void matchMembersInType(List<Result> results,
                        String text, String typeText, String memberText) {
  var searchText = new SearchText(text);
  var typeSearchText = new SearchText(typeText);
  var memberSearchText = new SearchText(memberText);
  for (Map<String,dynamic> library in libraryList)  {
    String libraryName = library[NAME];
    if (library.containsKey(TYPES)) {
      for (Map<String,dynamic> type in library[TYPES]) {
        String typeName = type[NAME];
        StringMatch typeMatch = obtainMatch(typeSearchText, typeName);
        if (typeMatch != null) {
          if (type.containsKey(MEMBERS)) {
            for (Map<String,dynamic> member in type[MEMBERS]) {
              // Check for constructor match.
              StringMatch constructorMatch = obtainMatch(searchText,
                  member[NAME]);
              if (constructorMatch != null) {
                results.add(new Result(constructorMatch, member[KIND],
                    getTypeMemberUrl(libraryName, typeName, member),
                    library: libraryName, noargs: member[NO_PARAMS]));
              } else {
                // Try member match.
                StringMatch memberMatch = obtainMatch(memberSearchText,
                    member[NAME]);
                if (memberMatch != null) {
                  results.add(new Result(memberMatch, member[KIND],
                      getTypeMemberUrl(libraryName, typeName, member),
                      library: libraryName, prefix: typeMatch,
                      args: type[ARGS], noargs: member[NO_PARAMS]));
                }
              }
            }
          }
        }
      }
    }
  }
}

void matchLibrary(List<Result> results, SearchText searchText, Map library) {
  String libraryName = library[NAME];
  StringMatch libraryMatch = obtainMatch(searchText, libraryName);
  if (libraryMatch != null) {
    results.add(new Result(libraryMatch, LIBRARY,
                           getLibraryUrl(libraryName)));
  }
}

void matchLibraryMembers(List<Result> results, SearchText searchText,
                          Map library) {
  if (library.containsKey(MEMBERS)) {
    String libraryName = library[NAME];
    for (Map<String,dynamic> member in library[MEMBERS]) {
      StringMatch memberMatch = obtainMatch(searchText, member[NAME]);
      if (memberMatch != null) {
        results.add(new Result(memberMatch, member[KIND],
                               getLibraryMemberUrl(libraryName, member),
                               library: libraryName, noargs: member[NO_PARAMS]));
      }
    }
  }
}

void matchTypes(List<Result> results, SearchText searchText,
                Map library) {
  if (library.containsKey(TYPES)) {
    String libraryName = library[NAME];
    for (Map<String,dynamic> type in library[TYPES]) {
      String typeName = type[NAME];
      matchType(results, searchText, libraryName, type);
      matchTypeMembers(results, searchText, libraryName, type);
    }
  }
}

void matchType(List<Result> results, SearchText searchText,
               String libraryName, Map type) {
  String typeName = type[NAME];
  StringMatch typeMatch = obtainMatch(searchText, typeName);
  if (typeMatch != null) {
    results.add(new Result(typeMatch, type[KIND],
                           getTypeUrl(libraryName, type),
                           library: libraryName, args: type[ARGS]));
  }
}

void matchTypeMembers(List<Result> results, SearchText searchText,
                      String libraryName, Map type) {
  if (type.containsKey(MEMBERS)) {
    String typeName = type[NAME];
    for (Map<String,dynamic> member in type[MEMBERS]) {
      StringMatch memberMatch = obtainMatch(searchText, member[NAME]);
      if (memberMatch != null) {
        results.add(new Result(memberMatch, member[KIND],
            getTypeMemberUrl(libraryName, typeName, member),
            library: libraryName, type: typeName, args: type[ARGS],
            noargs: member[NO_PARAMS]));
      }
    }
  }
}

String currentSearchText;
Result _currentResult;
List<Result> currentResults = const <Result>[];

void updateResults(String searchText, List<Result> results) {
  currentSearchText = searchText;
  currentResults = results;
  if (currentResults.isEmpty) {
    _currentResultIndex = -1;
    currentResult = null;
  } else {
    _currentResultIndex = 0;
    currentResult = currentResults[0];
  }
}

int _currentResultIndex;

void set currentResultIndex(int index) {
  if (index < -1) {
    return;
  }
  if (index >= currentResults.length) {
    return;
  }
  if (index != _currentResultIndex) {
    _currentResultIndex = index;
    if (index >= 0) {
      currentResult = currentResults[_currentResultIndex];
    } else {
      currentResult = null;
    }
  }
}

int get currentResultIndex => _currentResultIndex;

void set currentResult(Result result) {
  if (_currentResult != result) {
    if (_currentResult != null) {
      _currentResult.row.classes.remove('drop-down-link-select');
    }
    _currentResult = result;
    if (_currentResult != null) {
      _currentResult.row.classes.add('drop-down-link-select');
    }
  }
}

Result get currentResult => _currentResult;

/**
 * Navigate the search drop down using up/down inside the search field. Follow
 * the result link on enter.
 */
void handleUpDown(KeyboardEvent event) {
  if (event.keyIdentifier == KeyName.UP) {
    currentResultIndex--;
    event.preventDefault();
  } else if (event.keyIdentifier == KeyName.DOWN) {
    currentResultIndex++;
    event.preventDefault();
  } else if (event.keyIdentifier == KeyName.ENTER) {
    if (currentResult != null) {
      window.location.href = currentResult.url;
      event.preventDefault();
      hideDropDown();
    }
  }
}

/** Show the search drop down unless there are no current results. */
void showDropDown() {
  if (currentResults.isEmpty) {
    hideDropDown();
  } else {
    dropdown.style.visibility = 'visible';
  }
}

/** Used to prevent hiding the drop down when it is clicked. */
bool hideDropDownSuspend = false;

/** Hide the search drop down unless suspended. */
void hideDropDown() {
  if (hideDropDownSuspend) return;

  dropdown.style.visibility = 'hidden';
}

/** Activate search on Ctrl+3 and S. */
void shortcutHandler(KeyboardEvent event) {
  if (event.keyCode == 0x33/* 3 */ && event.ctrlKey) {
    searchInput.focus();
    event.preventDefault();
  } else if (event.target != searchInput && event.keyCode == 0x53/* S */) {
    // Allow writing 's' in the search input.
    searchInput.focus();
    event.preventDefault();
  }
}

/**
 * Setup window shortcuts.
 */
void setupShortcuts() {
  window.on.keyDown.add(shortcutHandler);
}

/** Setup search hooks. */
void setupSearch(var libraries) {
  libraryList = libraries;
  searchInput = query('#q');
  dropdown = query('#drop-down');

  searchInput.on.keyDown.add(handleUpDown);
  searchInput.on.keyUp.add(updateDropDown);
  searchInput.on.change.add(updateDropDown);
  searchInput.on.reset.add(updateDropDown);
  searchInput.on.focus.add((event) => showDropDown());
  searchInput.on.blur.add((event) => hideDropDown());
}