// 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.DiffPreferences;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.ChangeEditApi;
import com.google.gerrit.client.changes.ChangeInfo;
import com.google.gerrit.client.diff.DiffApi;
import com.google.gerrit.client.diff.DiffInfo;
import com.google.gerrit.client.diff.FileInfo;
import com.google.gerrit.client.diff.Header;
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.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.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.shared.HandlerRegistration;
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.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 net.codemirror.lib.CodeMirror;
import net.codemirror.lib.CodeMirror.ChangesHandler;
import net.codemirror.lib.Configuration;
import net.codemirror.lib.KeyMap;
import net.codemirror.lib.Pos;
import net.codemirror.mode.ModeInfo;
import net.codemirror.mode.ModeInjector;
import net.codemirror.theme.ThemeLoader;

import java.util.List;

public class EditScreen extends Screen {
  interface Binder extends UiBinder<HTMLPanel, EditScreen> {}
  private static final Binder uiBinder = GWT.create(Binder.class);

  private final PatchSet.Id base;
  private final PatchSet.Id revision;
  private final String path;
  private final int startLine;
  private DiffPreferences prefs;
  private CodeMirror cm;
  private HttpResponse<NativeString> content;
  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 Button close;
  @UiField Button save;
  @UiField Element editor;

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

  public EditScreen(PatchSet.Id base, Patch.Key patch, int startLine) {
    this.base = base;
    this.revision = patch.getParentKey();
    this.path = patch.get();
    this.startLine = startLine - 1;
    prefs = DiffPreferences.create(Gerrit.getAccountDiffPreference());
    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();

    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();
        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, null, null));
          }

          @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) {
            }
          }));
    } 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)
        .base(base)
        .webLinksOnly()
        .get(group1.add(new AsyncCallback<DiffInfo>() {
          @Override
          public void onSuccess(DiffInfo diffInfo) {
            diffLinks = diffInfo.web_links();
          }

          @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 (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(content);
        content = null;

        renderLinks(editFileInfo, diffLinks);
        editFileInfo = null;
        diffLinks = null;
      }
    });
    group1.done();
  }

  @Override
  public void registerKeys() {
    super.registerKeys();
    cm.addKeyMap(KeyMap.create()
        .on("Ctrl-L", gotoLine())
        .on("Cmd-L", gotoLine()));
  }

  private Runnable gotoLine() {
    return new Runnable() {
      @Override
      public void run() {
        String n = Window.prompt(EditConstants.I.gotoLineNumber(), "");
        if (n != null) {
          try {
            int line = Integer.parseInt(n);
            line--;
            if (line >= 0) {
              cm.scrollToLine(line);
            }
          } catch (NumberFormatException e) {
            // ignore non valid numbers
            // We don't want to popup another ugly dialog just to say
            // "The number you've provided is invalid, try again"
          }
        }
      }
    };
  }

  @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) {
        cm.adjustHeight(header.getOffsetHeight());
      }
    });
    closeHandler = Window.addWindowClosingHandler(new ClosingHandler() {
      @Override
      public void onWindowClosing(ClosingEvent event) {
        if (!cm.isClean(generation)) {
          event.setMessage(EditConstants.I.closeUnsavedChanges());
        }
      }
    });

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

    cm.adjustHeight(header.getOffsetHeight());
    cm.on("cursorActivity", updateCursorPosition());
    cm.extras().showTabs(prefs.showTabs());
    cm.extras().lineLength(
        Patch.COMMIT_MSG.equals(path) ? 72 : prefs.lineLength());
    cm.refresh();
    cm.focus();

    if (startLine > 0) {
      cm.scrollToLine(startLine);
    }
    updateActiveLine();
  }

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

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

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

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

  private void initEditor(HttpResponse<NativeString> file) {
    ModeInfo mode = null;
    String content = "";
    if (file != null && file.getResult() != null) {
      content = file.getResult().asString();
      if (prefs.syntaxHighlighting()) {
        mode = ModeInfo.findMode(file.getContentType(), path);
      }
    }
    cm = CodeMirror.create(editor, Configuration.create()
        .set("value", content)
        .set("readOnly", false)
        .set("cursorBlinkRate", 0)
        .set("cursorHeight", 0.85)
        .set("lineNumbers", true)
        .set("tabSize", prefs.tabSize())
        .set("lineWrapping", false)
        .set("scrollbarStyle", "overlay")
        .set("styleSelectedText", true)
        .set("showTrailingSpace", true)
        .set("keyMap", "default")
        .set("theme", prefs.theme().name().toLowerCase())
        .set("mode", mode != null ? mode.mode() : null));
    cm.addKeyMap(KeyMap.create()
        .on("Cmd-S", save())
        .on("Ctrl-S", save()));
  }

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

    if (editInfo != null) {
      renderLinks(Natives.asList(editInfo.web_links()));
    } 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", base, 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", base, 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() {
            cm.operation(new Runnable() {
              @Override
              public void run() {
                updateActiveLine();
              }
            });
          }
        });
      }
    };
  }

  private void updateActiveLine() {
    Pos p = cm.getCursor("end");
    cursLine.setInnerText(Integer.toString(p.line() + 1));
    cursCol.setInnerText(Integer.toString(p.ch() + 1));
    cm.extras().activeLine(cm.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 (!cm.isClean(generation)) {
          close.setEnabled(false);
          String text = cm.getValue();
          if (Patch.COMMIT_MSG.equals(path)) {
            String trimmed = text.trim() + "\r";
            if (!trimmed.equals(text)) {
              text = trimmed;
              cm.setValue(text);
            }
          }
          final int g = cm.changeGeneration(false);
          ChangeEditApi.put(revision.getParentKey().get(), path, text,
              new GerritCallback<VoidResult>() {
                @Override
                public void onSuccess(VoidResult result) {
                  generation = g;
                  setClean(cm.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);
  }
}
