// 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 com.google.gerrit.client.editor;

import static com.google.gwt.dom.client.Style.Visibility.HIDDEN;
import static com.google.gwt.dom.client.Style.Visibility.VISIBLE;

import com.google.gerrit.client.DiffWebLinkInfo;
import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.JumpKeys;
import com.google.gerrit.client.VoidResult;
import com.google.gerrit.client.account.EditPreferences;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.ChangeEditApi;
import com.google.gerrit.client.diff.DiffApi;
import com.google.gerrit.client.diff.DiffInfo;
import com.google.gerrit.client.diff.Header;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.info.FileInfo;
import com.google.gerrit.client.patches.PatchUtil;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.HttpCallback;
import com.google.gerrit.client.rpc.HttpResponse;
import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.InlineHyperlink;
import com.google.gerrit.client.ui.Screen;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.extensions.client.KeyMapType;
import com.google.gerrit.extensions.client.Theme;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Window.ClosingEvent;
import com.google.gwt.user.client.Window.ClosingHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.ImageResourceRenderer;
import com.google.gwtexpui.globalkey.client.GlobalKey;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import java.util.List;
import net.codemirror.addon.AddonInjector;
import net.codemirror.addon.Addons;
import net.codemirror.lib.CodeMirror;
import net.codemirror.lib.CodeMirror.ChangesHandler;
import net.codemirror.lib.CodeMirror.CommandRunner;
import net.codemirror.lib.Configuration;
import net.codemirror.lib.KeyMap;
import net.codemirror.lib.MergeView;
import net.codemirror.lib.Pos;
import net.codemirror.mode.ModeInfo;
import net.codemirror.mode.ModeInjector;
import net.codemirror.theme.ThemeLoader;

public class EditScreen extends Screen {
  interface Binder extends UiBinder<HTMLPanel, EditScreen> {}

  private static final Binder uiBinder = GWT.create(Binder.class);

  interface Style extends CssResource {
    String fullWidth();

    String base();

    String hideBase();
  }

  private final PatchSet.Id revision;
  private final String path;
  private final int startLine;
  private EditPreferences prefs;
  private EditPreferencesAction editPrefsAction;
  private MergeView mv;
  private CodeMirror cmBase;
  private CodeMirror cmEdit;
  private HttpResponse<NativeString> content;
  private HttpResponse<NativeString> baseContent;
  private EditFileInfo editFileInfo;
  private JsArray<DiffWebLinkInfo> diffLinks;

  @UiField Element header;
  @UiField Element project;
  @UiField Element filePath;
  @UiField FlowPanel linkPanel;
  @UiField Element cursLine;
  @UiField Element cursCol;
  @UiField Element dirty;
  @UiField CheckBox showBase;
  @UiField Button close;
  @UiField Button save;
  @UiField Element editor;
  @UiField Style style;

  private HandlerRegistration resizeHandler;
  private HandlerRegistration closeHandler;
  private int generation;

  public EditScreen(Patch.Key patch, int startLine) {
    this.revision = patch.getParentKey();
    this.path = patch.get();
    this.startLine = startLine - 1;
    setRequiresSignIn(true);
    add(uiBinder.createAndBindUi(this));
    addDomHandler(GlobalKey.STOP_PROPAGATION, KeyPressEvent.getType());
  }

  @Override
  protected void onInitUI() {
    super.onInitUI();
    setHeaderVisible(false);
    setWindowTitle(FileInfo.getFileName(path));
  }

  @Override
  protected void onLoad() {
    super.onLoad();

    prefs = EditPreferences.create(Gerrit.getEditPreferences());

    CallbackGroup group1 = new CallbackGroup();
    final CallbackGroup group2 = new CallbackGroup();
    final CallbackGroup group3 = new CallbackGroup();

    CodeMirror.initLibrary(
        group1.add(
            new AsyncCallback<Void>() {
              final AsyncCallback<Void> themeCallback = group3.addEmpty();

              @Override
              public void onSuccess(Void result) {
                // Load theme after CM library to ensure theme can override CSS.
                ThemeLoader.loadTheme(prefs.theme(), themeCallback);
                group2.done();

                new AddonInjector()
                    .add(Addons.I.merge_bundled().getName())
                    .inject(
                        new AsyncCallback<Void>() {
                          @Override
                          public void onFailure(Throwable caught) {}

                          @Override
                          public void onSuccess(Void result) {
                            if (!prefs.showBase() || revision.get() > 0) {
                              group3.done();
                            }
                          }
                        });
              }

              @Override
              public void onFailure(Throwable caught) {}
            }));

    ChangeApi.detail(
        revision.getParentKey().get(),
        group1.add(
            new AsyncCallback<ChangeInfo>() {
              @Override
              public void onSuccess(ChangeInfo c) {
                project.setInnerText(c.project());
                SafeHtml.setInnerHTML(filePath, Header.formatPath(path));
              }

              @Override
              public void onFailure(Throwable caught) {}
            }));

    if (revision.get() == 0) {
      ChangeEditApi.getMeta(
          revision,
          path,
          group1.add(
              new AsyncCallback<EditFileInfo>() {
                @Override
                public void onSuccess(EditFileInfo editInfo) {
                  editFileInfo = editInfo;
                }

                @Override
                public void onFailure(Throwable e) {}
              }));

      if (prefs.showBase()) {
        ChangeEditApi.get(
            revision,
            path,
            true /* base */,
            group1.addFinal(
                new HttpCallback<NativeString>() {
                  @Override
                  public void onSuccess(HttpResponse<NativeString> fc) {
                    baseContent = fc;
                    group3.done();
                  }

                  @Override
                  public void onFailure(Throwable e) {}
                }));
      } else {
        group1.done();
      }
    } else {
      // TODO(davido): We probably want to create dedicated GET EditScreenMeta
      // REST endpoint. Abuse GET diff for now, as it retrieves links we need.
      DiffApi.diff(revision, path)
          .webLinksOnly()
          .get(
              group1.addFinal(
                  new AsyncCallback<DiffInfo>() {
                    @Override
                    public void onSuccess(DiffInfo diffInfo) {
                      diffLinks = diffInfo.webLinks();
                    }

                    @Override
                    public void onFailure(Throwable e) {}
                  }));
    }

    ChangeEditApi.get(
        revision,
        path,
        group2.add(
            new HttpCallback<NativeString>() {
              final AsyncCallback<Void> modeCallback = group3.addEmpty();

              @Override
              public void onSuccess(HttpResponse<NativeString> fc) {
                content = fc;
                if (revision.get() > 0) {
                  baseContent = fc;
                }

                if (prefs.syntaxHighlighting()) {
                  injectMode(fc.getContentType(), modeCallback);
                } else {
                  modeCallback.onSuccess(null);
                }
              }

              @Override
              public void onFailure(Throwable e) {
                // "Not Found" means it's a new file.
                if (RestApi.isNotFound(e)) {
                  content = null;
                  modeCallback.onSuccess(null);
                } else {
                  GerritCallback.showFailure(e);
                }
              }
            }));

    group3.addListener(
        new ScreenLoadCallback<Void>(this) {
          @Override
          protected void preDisplay(Void result) {
            initEditor();

            renderLinks(editFileInfo, diffLinks);
            editFileInfo = null;
            diffLinks = null;

            showBase.setValue(prefs.showBase(), true);
            cmBase.refresh();
          }
        });
  }

  @Override
  public void registerKeys() {
    super.registerKeys();
    KeyMap localKeyMap = KeyMap.create();
    localKeyMap.on("Ctrl-L", gotoLine()).on("Cmd-L", gotoLine()).on("Cmd-S", save());

    // TODO(davido): Find a better way to prevent key maps collisions
    if (prefs.keyMapType() != KeyMapType.EMACS) {
      localKeyMap.on("Ctrl-S", save());
    }

    cmBase.addKeyMap(localKeyMap);
    cmEdit.addKeyMap(localKeyMap);
  }

  private Runnable gotoLine() {
    return new Runnable() {
      @Override
      public void run() {
        cmEdit.execCommand("jumpToLine");
      }
    };
  }

  @Override
  public void onShowView() {
    super.onShowView();
    Window.enableScrolling(false);
    JumpKeys.enable(false);
    if (prefs.hideTopMenu()) {
      Gerrit.setHeaderVisible(false);
    }
    resizeHandler =
        Window.addResizeHandler(
            new ResizeHandler() {
              @Override
              public void onResize(ResizeEvent event) {
                adjustHeight();
              }
            });
    closeHandler =
        Window.addWindowClosingHandler(
            new ClosingHandler() {
              @Override
              public void onWindowClosing(ClosingEvent event) {
                if (!cmEdit.isClean(generation)) {
                  event.setMessage(EditConstants.I.closeUnsavedChanges());
                }
              }
            });

    generation = cmEdit.changeGeneration(true);
    setClean(true);
    cmEdit.on(
        new ChangesHandler() {
          @Override
          public void handle(CodeMirror cm) {
            setClean(cm.isClean(generation));
          }
        });

    adjustHeight();
    cmEdit.on("cursorActivity", updateCursorPosition());
    setShowTabs(prefs.showTabs());
    setLineLength(prefs.lineLength());
    cmEdit.refresh();
    cmEdit.focus();

    if (startLine > 0) {
      cmEdit.scrollToLine(startLine);
    }
    updateActiveLine();
    editPrefsAction = new EditPreferencesAction(this, prefs);
  }

  @Override
  protected void onUnload() {
    super.onUnload();
    if (cmBase != null) {
      cmBase.getWrapperElement().removeFromParent();
    }
    if (cmEdit != null) {
      cmEdit.getWrapperElement().removeFromParent();
    }
    if (resizeHandler != null) {
      resizeHandler.removeHandler();
    }
    if (closeHandler != null) {
      closeHandler.removeHandler();
    }
    Window.enableScrolling(true);
    Gerrit.setHeaderVisible(true);
    JumpKeys.enable(true);
  }

  CodeMirror getEditor() {
    return cmEdit;
  }

  @UiHandler("editSettings")
  void onEditSetting(@SuppressWarnings("unused") ClickEvent e) {
    editPrefsAction.show();
  }

  @UiHandler("save")
  void onSave(@SuppressWarnings("unused") ClickEvent e) {
    save().run();
  }

  @UiHandler("close")
  void onClose(@SuppressWarnings("unused") ClickEvent e) {
    if (cmEdit.isClean(generation) || Window.confirm(EditConstants.I.cancelUnsavedChanges())) {
      upToChange();
    }
  }

  private void displayBase() {
    cmBase.getWrapperElement().getParentElement().removeClassName(style.hideBase());
    cmEdit.getWrapperElement().getParentElement().removeClassName(style.fullWidth());
    mv.getGapElement().removeClassName(style.hideBase());
    setCmBaseValue();
    setLineLength(prefs.lineLength());
    cmBase.refresh();
  }

  @UiHandler("showBase")
  void onShowBase(ValueChangeEvent<Boolean> e) {
    boolean shouldShow = e.getValue();
    if (shouldShow) {
      if (baseContent == null) {
        ChangeEditApi.get(
            revision,
            path,
            true /* base */,
            new HttpCallback<NativeString>() {
              @Override
              public void onSuccess(HttpResponse<NativeString> fc) {
                baseContent = fc;
                displayBase();
              }

              @Override
              public void onFailure(Throwable e) {}
            });
      } else {
        displayBase();
      }
    } else {
      cmBase.getWrapperElement().getParentElement().addClassName(style.hideBase());
      cmEdit.getWrapperElement().getParentElement().addClassName(style.fullWidth());
      mv.getGapElement().addClassName(style.hideBase());
    }
    mv.setShowDifferences(shouldShow);
  }

  void setOption(String option, String value) {
    cmBase.setOption(option, value);
    cmEdit.setOption(option, value);
  }

  void setOption(String option, boolean value) {
    cmBase.setOption(option, value);
    cmEdit.setOption(option, value);
  }

  void setOption(String option, double value) {
    cmBase.setOption(option, value);
    cmEdit.setOption(option, value);
  }

  void setTheme(final Theme newTheme) {
    cmBase.operation(
        new Runnable() {
          @Override
          public void run() {
            cmBase.setOption("theme", newTheme.name().toLowerCase());
          }
        });
    cmEdit.operation(
        new Runnable() {
          @Override
          public void run() {
            cmEdit.setOption("theme", newTheme.name().toLowerCase());
          }
        });
  }

  void setLineLength(int length) {
    int adjustedLength = Patch.COMMIT_MSG.equals(path) ? 72 : length;
    cmBase.extras().lineLength(adjustedLength);
    cmEdit.extras().lineLength(adjustedLength);
  }

  void setIndentUnit(int indent) {
    cmEdit.setOption("indentUnit", Patch.COMMIT_MSG.equals(path) ? 2 : indent);
  }

  void setShowLineNumbers(boolean show) {
    cmBase.setOption("lineNumbers", show);
    cmEdit.setOption("lineNumbers", show);
  }

  void setShowWhitespaceErrors(final boolean show) {
    cmBase.operation(
        new Runnable() {
          @Override
          public void run() {
            cmBase.setOption("showTrailingSpace", show);
          }
        });
    cmEdit.operation(
        new Runnable() {
          @Override
          public void run() {
            cmEdit.setOption("showTrailingSpace", show);
          }
        });
  }

  void setShowTabs(boolean show) {
    cmBase.extras().showTabs(show);
    cmEdit.extras().showTabs(show);
  }

  void adjustHeight() {
    int height = header.getOffsetHeight();
    int rest = Gerrit.getHeaderFooterHeight() + height + 5; // Estimate
    mv.getGapElement().getStyle().setHeight(Window.getClientHeight() - rest, Unit.PX);
    cmBase.adjustHeight(height);
    cmEdit.adjustHeight(height);
  }

  void setSyntaxHighlighting(boolean b) {
    ModeInfo modeInfo = ModeInfo.findMode(content.getContentType(), path);
    final String mode = modeInfo != null ? modeInfo.mime() : null;
    if (b && mode != null && !mode.isEmpty()) {
      injectMode(
          mode,
          new AsyncCallback<Void>() {
            @Override
            public void onSuccess(Void result) {
              cmBase.setOption("mode", mode);
              cmEdit.setOption("mode", mode);
            }

            @Override
            public void onFailure(Throwable caught) {
              prefs.syntaxHighlighting(false);
            }
          });
    } else {
      cmBase.setOption("mode", (String) null);
      cmEdit.setOption("mode", (String) null);
    }
  }

  private void upToChange() {
    Gerrit.display(PageLinks.toChangeInEditMode(revision.getParentKey()));
  }

  private void initEditor() {
    ModeInfo mode = null;
    String editContent = "";
    if (content != null && content.getResult() != null) {
      editContent = content.getResult().asString();
      if (prefs.syntaxHighlighting()) {
        mode = ModeInfo.findMode(content.getContentType(), path);
      }
    }

    Configuration cfg =
        Configuration.create()
            .set("autoCloseBrackets", prefs.autoCloseBrackets())
            .set("cursorBlinkRate", prefs.cursorBlinkRate())
            .set("cursorHeight", 0.85)
            .set("indentUnit", prefs.indentUnit())
            .set("keyMap", prefs.keyMapType().name().toLowerCase())
            .set("lineNumbers", prefs.hideLineNumbers())
            .set("lineWrapping", prefs.lineWrapping())
            .set("indentWithTabs", prefs.indentWithTabs())
            .set("matchBrackets", prefs.matchBrackets())
            .set("mode", mode != null ? mode.mime() : null)
            .set("origLeft", editContent)
            .set("scrollbarStyle", "overlay")
            .set("showTrailingSpace", prefs.showWhitespaceErrors())
            .set("styleSelectedText", true)
            .set("tabSize", prefs.tabSize())
            .set("theme", prefs.theme().name().toLowerCase())
            .set("value", "");

    if (editContent.contains("\r\n")) {
      cfg.set("lineSeparator", "\r\n");
    }

    mv = MergeView.create(editor, cfg);

    cmBase = mv.leftOriginal();
    cmBase.getWrapperElement().addClassName(style.base());
    cmEdit = mv.editor();
    setCmBaseValue();
    cmEdit.setValue(editContent);

    CodeMirror.addCommand(
        "save",
        new CommandRunner() {
          @Override
          public void run(CodeMirror instance) {
            save().run();
          }
        });
  }

  private void renderLinks(EditFileInfo editInfo, JsArray<DiffWebLinkInfo> diffLinks) {
    renderLinksToDiff();

    if (editInfo != null) {
      renderLinks(Natives.asList(editInfo.webLinks()));
    } else if (diffLinks != null) {
      renderLinks(Natives.asList(diffLinks));
    }
  }

  private void renderLinks(List<DiffWebLinkInfo> links) {
    if (links != null) {
      for (DiffWebLinkInfo webLink : links) {
        linkPanel.add(webLink.toAnchor());
      }
    }
  }

  private void renderLinksToDiff() {
    InlineHyperlink sbs = new InlineHyperlink();
    sbs.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.sideBySideDiff()));
    sbs.setTargetHistoryToken(
        Dispatcher.toPatch("sidebyside", null, new Patch.Key(revision, path)));
    sbs.setTitle(PatchUtil.C.sideBySideDiff());
    linkPanel.add(sbs);

    InlineHyperlink unified = new InlineHyperlink();
    unified.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.unifiedDiff()));
    unified.setTargetHistoryToken(
        Dispatcher.toPatch("unified", null, new Patch.Key(revision, path)));
    unified.setTitle(PatchUtil.C.unifiedDiff());
    linkPanel.add(unified);
  }

  private Runnable updateCursorPosition() {
    return new Runnable() {
      @Override
      public void run() {
        // The rendering of active lines has to be deferred. Reflow
        // caused by adding and removing styles chokes Firefox when arrow
        // key (or j/k) is held down. Performance on Chrome is fine
        // without the deferral.
        //
        Scheduler.get()
            .scheduleDeferred(
                new ScheduledCommand() {
                  @Override
                  public void execute() {
                    cmEdit.operation(
                        new Runnable() {
                          @Override
                          public void run() {
                            updateActiveLine();
                          }
                        });
                  }
                });
      }
    };
  }

  private void updateActiveLine() {
    Pos p = cmEdit.getCursor("end");
    cursLine.setInnerText(Integer.toString(p.line() + 1));
    cursCol.setInnerText(Integer.toString(p.ch() + 1));
    cmEdit.extras().activeLine(cmEdit.getLineHandleVisualStart(p.line()));
  }

  private void setClean(boolean clean) {
    save.setEnabled(!clean);
    close.setEnabled(true);
    dirty.getStyle().setVisibility(!clean ? VISIBLE : HIDDEN);
  }

  private Runnable save() {
    return new Runnable() {
      @Override
      public void run() {
        if (!cmEdit.isClean(generation)) {
          close.setEnabled(false);
          String text = cmEdit.getValue();
          if (Patch.COMMIT_MSG.equals(path)) {
            String trimmed = text.trim() + "\r";
            if (!trimmed.equals(text)) {
              text = trimmed;
              cmEdit.setValue(text);
            }
          }
          final int g = cmEdit.changeGeneration(false);
          ChangeEditApi.put(
              revision.getParentKey().get(),
              path,
              text,
              new GerritCallback<VoidResult>() {
                @Override
                public void onSuccess(VoidResult result) {
                  generation = g;
                  setClean(cmEdit.isClean(g));
                }

                @Override
                public void onFailure(final Throwable caught) {
                  close.setEnabled(true);
                }
              });
        }
      }
    };
  }

  private void injectMode(String type, AsyncCallback<Void> cb) {
    new ModeInjector().add(type).inject(cb);
  }

  private void setCmBaseValue() {
    cmBase.setValue(
        baseContent != null && baseContent.getResult() != null
            ? baseContent.getResult().asString()
            : "");
  }
}
