// Copyright (C) 2013 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.change;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.account.AccountApi;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.ChangeInfo;
import com.google.gerrit.client.changes.ChangeInfo.FetchInfo;
import com.google.gerrit.client.changes.ChangeList;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.extensions.common.ListChangesOption;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadScheme;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.clippy.client.CopyableLabel;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;

class DownloadBox extends VerticalPanel {
  private final ChangeInfo change;
  private final String revision;
  private final PatchSet.Id psId;
  private final FlexTable commandTable;
  private final ListBox scheme;
  private NativeMap<FetchInfo> fetch;

  DownloadBox(ChangeInfo change, String revision, PatchSet.Id psId) {
    this.change = change;
    this.revision = revision;
    this.psId = psId;
    this.commandTable = new FlexTable();
    this.scheme = new ListBox();
    this.scheme.addChangeHandler(new ChangeHandler() {
      @Override
      public void onChange(ChangeEvent event) {
        renderCommands();
        if (Gerrit.isSignedIn()) {
          saveScheme();
        }
      }
    });

    setStyleName(Gerrit.RESOURCES.css().downloadBox());
    commandTable.setStyleName(Gerrit.RESOURCES.css().downloadBoxTable());
    scheme.setStyleName(Gerrit.RESOURCES.css().downloadBoxScheme());
    add(commandTable);
  }

  @Override
  protected void onLoad() {
    if (fetch == null) {
      RestApi call = ChangeApi.detail(change.legacy_id().get());
      ChangeList.addOptions(call, EnumSet.of(
          revision.equals(change.current_revision())
             ? ListChangesOption.CURRENT_REVISION
             : ListChangesOption.ALL_REVISIONS,
          ListChangesOption.DOWNLOAD_COMMANDS));
      call.get(new AsyncCallback<ChangeInfo>() {
        @Override
        public void onSuccess(ChangeInfo result) {
          fetch = result.revision(revision).fetch();
          renderScheme();
        }

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

  private void renderCommands() {
    commandTable.removeAllRows();

    if (scheme.getItemCount() > 0) {
      FetchInfo fetchInfo =
          fetch.get(scheme.getValue(scheme.getSelectedIndex()));
      for (String commandName : Natives.keys(fetchInfo.commands())) {
        CopyableLabel copyLabel =
            new CopyableLabel(fetchInfo.command(commandName));
        copyLabel.setStyleName(Gerrit.RESOURCES.css().downloadBoxCopyLabel());
        insertCommand(commandName, copyLabel);
      }
    }
    if (change.revision(revision).commit().parents().length() == 1) {
      insertPatch();
    }
    insertArchive();
    insertCommand(null, scheme);
  }

  private void insertPatch() {
    String id = revision.substring(0, 7);
    Anchor patchBase64 = new Anchor(id + ".diff.base64");
    patchBase64.setHref(new RestApi("/changes/")
      .id(psId.getParentKey().get())
      .view("revisions")
      .id(revision)
      .view("patch")
      .addParameterTrue("download")
      .url());

    Anchor patchZip = new Anchor(id + ".diff.zip");
    patchZip.setHref(new RestApi("/changes/")
      .id(psId.getParentKey().get())
      .view("revisions")
      .id(revision)
      .view("patch")
      .addParameterTrue("zip")
      .url());

    HorizontalPanel p = new HorizontalPanel();
    p.add(patchBase64);
    InlineLabel spacer = new InlineLabel("|");
    spacer.setStyleName(Gerrit.RESOURCES.css().downloadBoxSpacer());
    p.add(spacer);
    p.add(patchZip);
    insertCommand("Patch-File", p);
  }

  private void insertArchive() {
    List<String> activated = Gerrit.getConfig().getArchiveFormats();
    if (activated.isEmpty()) {
      return;
    }

    List<Anchor> anchors = new ArrayList<>(activated.size());
    for (String f : activated) {
      Anchor archive = new Anchor(f);
      archive.setHref(new RestApi("/changes/")
          .id(psId.getParentKey().get())
          .view("revisions")
          .id(revision)
          .view("archive")
          .addParameter("format", f)
          .url());
      anchors.add(archive);
    }

    HorizontalPanel p = new HorizontalPanel();
    Iterator<Anchor> it = anchors.iterator();
    while (it.hasNext()) {
      Anchor a = it.next();
      p.add(a);
      if (it.hasNext()) {
        InlineLabel spacer = new InlineLabel("|");
        spacer.setStyleName(Gerrit.RESOURCES.css().downloadBoxSpacer());
        p.add(spacer);
      }
    }
    insertCommand("Archive", p);
  }

  private void insertCommand(String commandName, Widget w) {
    int row = commandTable.getRowCount();
    commandTable.insertRow(row);
    commandTable.getCellFormatter().addStyleName(row, 0,
        Gerrit.RESOURCES.css().downloadBoxTableCommandColumn());
    if (commandName != null) {
      commandTable.setText(row, 0, commandName);
    }
    if (w != null) {
      commandTable.setWidget(row, 1, w);
    }
  }

  private void renderScheme() {
    for (String id : fetch.keySet()) {
      scheme.addItem(id);
    }
    if (scheme.getItemCount() == 0) {
      scheme.setVisible(false);
    } else {
      if (scheme.getItemCount() == 1) {
        scheme.setSelectedIndex(0);
        scheme.setVisible(false);
      } else {
        int select = 0;
        String find = getUserPreference();
        if (find != null) {
          for (int i = 0; i < scheme.getItemCount(); i++) {
            if (find.equals(scheme.getValue(i))) {
              select = i;
              break;
            }
          }
        }
        scheme.setSelectedIndex(select);
      }
    }
    renderCommands();
  }

  private static String getUserPreference() {
    if (Gerrit.isSignedIn()) {
      DownloadScheme pref =
          Gerrit.getUserAccount().getGeneralPreferences().getDownloadUrl();
      if (pref != null) {
        switch (pref) {
          case ANON_GIT:
            return "git";
          case ANON_HTTP:
            return "anonymous http";
          case HTTP:
            return "http";
          case SSH:
            return "ssh";
          case REPO_DOWNLOAD:
            return "repo";
          default:
            return null;
        }
      }
    }
    return null;
  }

  private void saveScheme() {
    DownloadScheme scheme = getSelectedScheme();
    AccountGeneralPreferences pref =
        Gerrit.getUserAccount().getGeneralPreferences();

    if (scheme != null && scheme != pref.getDownloadUrl()) {
      pref.setDownloadUrl(scheme);
      PreferenceInput in = PreferenceInput.create();
      in.download_scheme(scheme);
      AccountApi.self().view("preferences")
          .post(in, new AsyncCallback<JavaScriptObject>() {
            @Override
            public void onSuccess(JavaScriptObject result) {
            }

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

  private DownloadScheme getSelectedScheme() {
    String id = scheme.getValue(scheme.getSelectedIndex());
    if ("git".equals(id)) {
      return DownloadScheme.ANON_GIT;
    } else if ("anonymous http".equals(id)) {
      return DownloadScheme.ANON_HTTP;
    } else if ("http".equals(id)) {
      return DownloadScheme.HTTP;
    } else if ("ssh".equals(id)) {
      return DownloadScheme.SSH;
    } else if ("repo".equals(id)) {
      return DownloadScheme.REPO_DOWNLOAD;
    }
    return null;
  }

  private static class PreferenceInput extends JavaScriptObject {
    static PreferenceInput create() {
      return createObject().cast();
    }

    final void download_scheme(DownloadScheme s) {
      download_scheme0(s.name());
    }

    private final native void download_scheme0(String n) /*-{
      this.download_scheme = n;
    }-*/;

    protected PreferenceInput() {
    }
  }
}
