// Copyright (C) 2014 The Android Open Source Project
//
// 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.

package net.codemirror.mode;

import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.Natives;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.resources.client.DataResource;
import com.google.gwt.safehtml.shared.SafeUri;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

/** Description of a CodeMirror language mode. */
public class ModeInfo extends JavaScriptObject {
  private static NativeMap<ModeInfo> byMime;
  private static NativeMap<ModeInfo> byExt;

  /** Map of names such as "clike" to URI for code download. */
  private static final Map<String, SafeUri> modeUris = new HashMap<>();

  static {
    indexModes(new DataResource[] {
      Modes.I.apl(),
      Modes.I.asciiarmor(),
      Modes.I.asn_1(),
      Modes.I.asterisk(),
      Modes.I.brainfuck(),
      Modes.I.clike(),
      Modes.I.clojure(),
      Modes.I.cmake(),
      Modes.I.cobol(),
      Modes.I.coffeescript(),
      Modes.I.commonlisp(),
      Modes.I.crystal(),
      Modes.I.css(),
      Modes.I.cypher(),
      Modes.I.d(),
      Modes.I.dart(),
      Modes.I.diff(),
      Modes.I.django(),
      Modes.I.dockerfile(),
      Modes.I.dtd(),
      Modes.I.dylan(),
      Modes.I.ebnf(),
      Modes.I.ecl(),
      Modes.I.eiffel(),
      Modes.I.elm(),
      Modes.I.erlang(),
      Modes.I.factor(),
      Modes.I.fcl(),
      Modes.I.forth(),
      Modes.I.fortran(),
      Modes.I.gas(),
      Modes.I.gerrit_commit(),
      Modes.I.gfm(),
      Modes.I.gherkin(),
      Modes.I.go(),
      Modes.I.groovy(),
      Modes.I.haml(),
      Modes.I.handlebars(),
      Modes.I.haskell_literate(),
      Modes.I.haskell(),
      Modes.I.haxe(),
      Modes.I.htmlembedded(),
      Modes.I.htmlmixed(),
      Modes.I.http(),
      Modes.I.idl(),
      Modes.I.jade(),
      Modes.I.javascript(),
      Modes.I.jinja2(),
      Modes.I.jsx(),
      Modes.I.julia(),
      Modes.I.livescript(),
      Modes.I.lua(),
      Modes.I.markdown(),
      Modes.I.mathematica(),
      Modes.I.mbox(),
      Modes.I.mirc(),
      Modes.I.mllike(),
      Modes.I.modelica(),
      Modes.I.mscgen(),
      Modes.I.mumps(),
      Modes.I.nginx(),
      Modes.I.nsis(),
      Modes.I.ntriples(),
      Modes.I.octave(),
      Modes.I.oz(),
      Modes.I.pascal(),
      Modes.I.pegjs(),
      Modes.I.perl(),
      Modes.I.php(),
      Modes.I.pig(),
      Modes.I.powershell(),
      Modes.I.properties(),
      Modes.I.protobuf(),
      Modes.I.puppet(),
      Modes.I.python(),
      Modes.I.q(),
      Modes.I.r(),
      Modes.I.rpm(),
      Modes.I.rst(),
      Modes.I.ruby(),
      Modes.I.rust(),
      Modes.I.sas(),
      Modes.I.sass(),
      Modes.I.scheme(),
      Modes.I.shell(),
      Modes.I.smalltalk(),
      Modes.I.smarty(),
      Modes.I.solr(),
      Modes.I.soy(),
      Modes.I.sparql(),
      Modes.I.spreadsheet(),
      Modes.I.sql(),
      Modes.I.stex(),
      Modes.I.stylus(),
      Modes.I.swift(),
      Modes.I.tcl(),
      Modes.I.textile(),
      Modes.I.tiddlywiki(),
      Modes.I.tiki(),
      Modes.I.toml(),
      Modes.I.tornado(),
      Modes.I.troff(),
      Modes.I.ttcn_cfg(),
      Modes.I.ttcn(),
      Modes.I.turtle(),
      Modes.I.twig(),
      Modes.I.vb(),
      Modes.I.vbscript(),
      Modes.I.velocity(),
      Modes.I.verilog(),
      Modes.I.vhdl(),
      Modes.I.vue(),
      Modes.I.webidl(),
      Modes.I.xml(),
      Modes.I.xquery(),
      Modes.I.yacas(),
      Modes.I.yaml_frontmatter(),
      Modes.I.yaml(),
      Modes.I.z80(),
    });

    alias("application/x-httpd-php-open", "application/x-httpd-php");
    alias("application/x-javascript", "application/javascript");
    alias("application/x-shellscript", "text/x-sh");
    alias("application/x-tcl", "text/x-tcl");
    alias("text/typescript", "application/typescript");
    alias("text/x-c", "text/x-csrc");
    alias("text/x-c++hdr", "text/x-c++src");
    alias("text/x-chdr", "text/x-csrc");
    alias("text/x-h", "text/x-csrc");
    alias("text/x-ini", "text/x-properties");
    alias("text/x-java-source", "text/x-java");
    alias("text/x-php", "application/x-httpd-php");
    alias("text/x-scripttcl", "text/x-tcl");
  }

  /** All supported modes. */
  public static native JsArray<ModeInfo> all() /*-{
    return $wnd.CodeMirror.modeInfo
  }-*/;

  private static native void setAll(JsArray<ModeInfo> m) /*-{
    $wnd.CodeMirror.modeInfo = m
  }-*/;

  /** Look up mode by primary or alternate MIME types. */
  public static ModeInfo findModeByMIME(String mime) {
    return byMime.get(mime);
  }

  public static SafeUri getModeScriptUri(String mode) {
    return modeUris.get(mode);
  }

  /** Look up mode by MIME type or file extension from a path. */
  public static ModeInfo findMode(String mime, String path) {
    ModeInfo m = byMime.get(mime);
    if (m != null) {
      return m;
    }

    int s = path.lastIndexOf('/');
    int d = path.lastIndexOf('.');
    if (d == -1 || s > d) {
      return null; // punt on "foo.src/bar" type paths.
    }

    if (byExt == null) {
      byExt = NativeMap.create();
      for (ModeInfo mode : Natives.asList(all())) {
        for (String ext : Natives.asList(mode.ext())) {
          byExt.put(ext, mode);
        }
      }
    }
    return byExt.get(path.substring(d + 1));
  }

  private static void alias(String serverMime, String toMime) {
    ModeInfo mode = byMime.get(toMime);
    if (mode != null) {
      byMime.put(serverMime, mode);
    }
  }

  private static void indexModes(DataResource[] all) {
    for (DataResource r : all) {
      modeUris.put(r.getName(), r.getSafeUri());
    }

    JsArray<ModeInfo> modeList = all();
    modeList.push(gerrit_commit());

    byMime = NativeMap.create();
    JsArray<ModeInfo> filtered = JsArray.createArray().cast();
    for (ModeInfo m : Natives.asList(modeList)) {
      if (modeUris.containsKey(m.mode())) {
        filtered.push(m);

        for (String mimeType : Natives.asList(m.mimes())) {
          byMime.put(mimeType, m);
        }
        byMime.put(m.mode(), m);
      }
    }
    Collections.sort(Natives.asList(filtered), new Comparator<ModeInfo>() {
      @Override
      public int compare(ModeInfo a, ModeInfo b) {
        return a.name().toLowerCase().compareTo(b.name().toLowerCase());
      }
    });
    setAll(filtered);
  }

  /** Human readable name of the mode, such as "C++". */
  public final native String name() /*-{ return this.name }-*/;

  /** Internal CodeMirror name for {@code mode.js} file to load. */
  public final native String mode() /*-{ return this.mode }-*/;

  /** Primary MIME type to activate this mode. */
  public final native String mime() /*-{ return this.mime }-*/;

  /** Primary and additional MIME types that activate this mode. */
  public final native JsArrayString mimes()
  /*-{ return this.mimes || [this.mime] }-*/;

  private native JsArrayString ext()
  /*-{ return this.ext || [] }-*/;

  protected ModeInfo() {
  }

  private static native ModeInfo gerrit_commit() /*-{
    return {name: "Git Commit Message",
            mime: "text/x-gerrit-commit-message",
            mode: "gerrit_commit"}
  }-*/;
}
