// 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.googlesource.gerrit.plugins.serviceuser.client;

import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.plugin.client.Plugin;
import com.google.gerrit.plugin.client.rpc.NoContent;
import com.google.gerrit.plugin.client.rpc.RestApi;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
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.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwtexpui.clippy.client.CopyableLabel;
import com.google.gwtexpui.globalkey.client.NpTextArea;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

class SshPanel extends Composite {
  private final String serviceUser;

  private SshKeyTable keys;

  private Button showAddKeyBlock;
  private Panel addKeyBlock;
  private Button closeAddKeyBlock;
  private Button clearNew;
  private Button addNew;
  private NpTextArea addTxt;
  private Button deleteKey;

  private Panel serverKeys;

  private int loadCount;

  SshPanel(String serviceUser) {
    this.serviceUser = serviceUser;

    FlowPanel body = new FlowPanel();

    showAddKeyBlock = new Button("Add Key ...");
    showAddKeyBlock.addClickHandler(
        new ClickHandler() {
          @Override
          public void onClick(final ClickEvent event) {
            showAddKeyBlock(true);
          }
        });

    keys = new SshKeyTable();
    body.add(keys);
    {
      final FlowPanel fp = new FlowPanel();
      deleteKey = new Button("Delete");
      deleteKey.setEnabled(false);
      deleteKey.addClickHandler(
          new ClickHandler() {
            @Override
            public void onClick(final ClickEvent event) {
              keys.deleteChecked();
            }
          });
      fp.add(deleteKey);
      fp.add(showAddKeyBlock);
      body.add(fp);
    }

    addKeyBlock = new VerticalPanel();
    addKeyBlock.setVisible(false);
    addKeyBlock.setStyleName("serviceuser-addSshKeyPanel");
    addKeyBlock.add(new Label("Add SSH Public Key"));
    addKeyBlock.add(new SshKeyHelpPanel());

    addTxt = new NpTextArea();
    addTxt.setVisibleLines(12);
    addTxt.setCharacterWidth(80);
    addTxt.setSpellCheck(false);
    addKeyBlock.add(addTxt);

    final HorizontalPanel buttons = new HorizontalPanel();
    addKeyBlock.add(buttons);

    clearNew = new Button("Clear");
    clearNew.addClickHandler(
        new ClickHandler() {
          @Override
          public void onClick(final ClickEvent event) {
            addTxt.setText("");
            addTxt.setFocus(true);
          }
        });
    buttons.add(clearNew);

    addNew = new Button("Add");
    addNew.addClickHandler(
        new ClickHandler() {
          @Override
          public void onClick(final ClickEvent event) {
            doAddNew();
          }
        });
    buttons.add(addNew);

    closeAddKeyBlock = new Button("Close");
    closeAddKeyBlock.addClickHandler(
        new ClickHandler() {
          @Override
          public void onClick(final ClickEvent event) {
            showAddKeyBlock(false);
          }
        });
    buttons.add(closeAddKeyBlock);
    buttons.setCellWidth(closeAddKeyBlock, "100%");
    buttons.setCellHorizontalAlignment(closeAddKeyBlock, HasHorizontalAlignment.ALIGN_RIGHT);

    body.add(addKeyBlock);

    serverKeys = new FlowPanel();
    body.add(serverKeys);

    initWidget(body);
  }

  void setKeyTableVisible(final boolean on) {
    keys.setVisible(on);
    deleteKey.setVisible(on);
    closeAddKeyBlock.setVisible(on);
  }

  void doAddNew() {
    final String txt = addTxt.getText();
    if (txt != null && txt.length() > 0) {
      new RestApi("config")
          .id("server")
          .view(Plugin.get().getPluginName(), "serviceusers")
          .id(serviceUser)
          .view("sshkeys")
          .post(
              txt,
              new AsyncCallback<SshKeyInfo>() {
                @Override
                public void onSuccess(SshKeyInfo k) {
                  addTxt.setText("");
                  keys.addOneKey(k);
                  if (!keys.isVisible()) {
                    showAddKeyBlock(false);
                    setKeyTableVisible(true);
                    keys.updateDeleteButton();
                  }
                }

                @Override
                public void onFailure(final Throwable caught) {
                  // never invoked
                }
              });
    }
  }

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

  private void refreshSshKeys() {
    new RestApi("config")
        .id("server")
        .view(Plugin.get().getPluginName(), "serviceusers")
        .id(serviceUser)
        .view("sshkeys")
        .get(
            new AsyncCallback<JsArray<SshKeyInfo>>() {
              @Override
              public void onSuccess(JsArray<SshKeyInfo> result) {
                keys.display(Natives.asList(result));
                if (result.length() == 0 && keys.isVisible()) {
                  showAddKeyBlock(true);
                }
                if (++loadCount == 2) {
                  display();
                }
              }

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

  void display() {}

  private void showAddKeyBlock(boolean show) {
    showAddKeyBlock.setVisible(!show);
    addKeyBlock.setVisible(show);
  }

  private class SshKeyTable extends FlexTable {
    private final Map<Integer, SshKeyInfo> sshKeyInfos;
    private ValueChangeHandler<Boolean> updateDeleteHandler;

    SshKeyTable() {
      this.sshKeyInfos = new HashMap<>();
      setStyleName("serviceuser-sshKeyTable");
      setWidth("");
      setText(0, 2, "Status");
      setText(0, 3, "Algorithm");
      setText(0, 4, "Key");
      setText(0, 5, "Comment");

      FlexCellFormatter fmt = getFlexCellFormatter();
      fmt.addStyleName(0, 1, "iconHeader");
      fmt.addStyleName(0, 2, "dataHeader");
      fmt.addStyleName(0, 3, "dataHeader");
      fmt.addStyleName(0, 4, "dataHeader");
      fmt.addStyleName(0, 5, "dataHeader");

      fmt.addStyleName(0, 1, "topMostCell");
      fmt.addStyleName(0, 2, "topMostCell");
      fmt.addStyleName(0, 3, "topMostCell");
      fmt.addStyleName(0, 4, "topMostCell");
      fmt.addStyleName(0, 5, "topMostCell");

      updateDeleteHandler =
          new ValueChangeHandler<Boolean>() {
            @Override
            public void onValueChange(ValueChangeEvent<Boolean> event) {
              updateDeleteButton();
            }
          };
    }

    void deleteChecked() {
      final HashSet<Integer> sequenceNumbers = new HashSet<>();
      for (int row = 1; row < getRowCount(); row++) {
        SshKeyInfo k = getRowItem(row);
        if (k != null && ((CheckBox) getWidget(row, 1)).getValue()) {
          sequenceNumbers.add(k.seq());
        }
      }
      if (sequenceNumbers.isEmpty()) {
        updateDeleteButton();
      } else {
        for (int seq : sequenceNumbers) {
          new RestApi("config")
              .id("server")
              .view(Plugin.get().getPluginName(), "serviceusers")
              .id(serviceUser)
              .view("sshkeys")
              .id(seq)
              .delete(
                  new AsyncCallback<NoContent>() {
                    @Override
                    public void onSuccess(NoContent result) {
                      for (int row = 1; row < getRowCount(); ) {
                        SshKeyInfo k = getRowItem(row);
                        if (k != null && sequenceNumbers.contains(k.seq())) {
                          removeRow(row);
                        } else {
                          row++;
                        }
                      }
                      if (getRowCount() == 1) {
                        display(Collections.<SshKeyInfo>emptyList());
                      } else {
                        updateDeleteButton();
                      }
                    }

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

    void display(List<SshKeyInfo> result) {
      if (result.isEmpty()) {
        setKeyTableVisible(false);
        showAddKeyBlock(true);
      } else {
        while (1 < getRowCount()) removeRow(getRowCount() - 1);
        for (SshKeyInfo k : result) {
          addOneKey(k);
        }
        setKeyTableVisible(true);
        deleteKey.setEnabled(false);
      }
    }

    void addOneKey(SshKeyInfo k) {
      FlexCellFormatter fmt = getFlexCellFormatter();
      int row = getRowCount();
      insertRow(row);
      getCellFormatter().addStyleName(row, 0, "iconCell");
      getCellFormatter().addStyleName(row, 0, "leftMostCell");

      CheckBox sel = new CheckBox();
      sel.addValueChangeHandler(updateDeleteHandler);

      setWidget(row, 1, sel);
      if (k.isValid()) {
        setText(row, 2, "");
        fmt.removeStyleName(row, 2, "serviceuser-sshKeyPanelInvalid");
      } else {
        setText(row, 2, "Invalid Key");
        fmt.addStyleName(row, 2, "serviceuser-sshKeyPanelInvalid");
      }
      setText(row, 3, k.algorithm());

      CopyableLabel keyLabel = new CopyableLabel(k.sshPublicKey());
      keyLabel.setPreviewText(elide(k.encodedKey(), 40));
      setWidget(row, 4, keyLabel);

      setText(row, 5, k.comment());

      fmt.addStyleName(row, 1, "iconCell");
      fmt.addStyleName(row, 4, "serviceuser-sshKeyPanelEncodedKey");
      for (int c = 2; c <= 5; c++) {
        fmt.addStyleName(row, c, "dataCell");
      }

      setRowItem(row, k);
    }

    void updateDeleteButton() {
      boolean on = false;
      for (int row = 1; row < getRowCount(); row++) {
        CheckBox sel = (CheckBox) getWidget(row, 1);
        if (sel.getValue()) {
          on = true;
          break;
        }
      }
      deleteKey.setEnabled(on);
    }

    private SshKeyInfo getRowItem(int row) {
      return sshKeyInfos.get(row);
    }

    private void setRowItem(int row, SshKeyInfo sshKeyInfo) {
      sshKeyInfos.put(row, sshKeyInfo);
    }
  }

  static String elide(String s, int len) {
    if (s == null || s.length() < len || len <= 10) {
      return s;
    }
    return s.substring(0, len - 10) + "..." + s.substring(s.length() - 10);
  }
}
