// 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.plugin.client.Plugin;
import com.google.gerrit.plugin.client.rpc.RestApi;
import com.google.gerrit.plugin.client.screen.Screen;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
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.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;

public class ServiceUserSettingsScreen extends VerticalPanel {
  static class Factory implements Screen.EntryPoint {
    @Override
    public void onLoad(Screen screen) {
      screen.setPageTitle("Service User Administration");
      screen.show(new ServiceUserSettingsScreen());
    }
  }

  private TextArea infoMsgTxt;
  private TextArea onSuccessMsgTxt;
  private CheckBox allowEmailCheckBox;
  private CheckBox allowHttpPasswordCheckBox;
  private CheckBox allowOwnerCheckBox;
  private CheckBox createNotesCheckBox;
  private CheckBox createNotesAsyncCheckBox;
  private StringListPanel blockedUsernamesPanel;
  private StringListPanel groupsPanel;
  private Button saveButton;

  ServiceUserSettingsScreen() {
    setStyleName("serviceuser-panel");

    new RestApi("config")
        .id("server")
        .view(Plugin.get().getPluginName(), "config")
        .get(
            new AsyncCallback<ConfigInfo>() {
              @Override
              public void onSuccess(ConfigInfo info) {
                display(info);
              }

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

  private void display(ConfigInfo info) {
    Panel infoMsgPanel = new VerticalPanel();
    Panel infoMsgTitelPanel = new HorizontalPanel();
    infoMsgTitelPanel.add(new Label("Info Message"));
    Image infoMsgInfo = new Image(ServiceUserPlugin.RESOURCES.info());
    infoMsgInfo.setTitle(
        "HTML formatted message that should be"
            + " displayed on the service user creation screen.");
    infoMsgTitelPanel.add(infoMsgInfo);
    infoMsgTitelPanel.add(new Label(":"));
    infoMsgPanel.add(infoMsgTitelPanel);
    infoMsgTxt = new TextArea();
    infoMsgTxt.setValue(info.getInfoMessage());
    infoMsgTxt.addKeyPressHandler(
        new KeyPressHandler() {
          @Override
          public void onKeyPress(final KeyPressEvent event) {
            event.stopPropagation();
          }
        });
    infoMsgTxt.setVisibleLines(12);
    infoMsgTxt.setCharacterWidth(80);
    infoMsgTxt.getElement().setPropertyBoolean("spellcheck", false);
    infoMsgPanel.add(infoMsgTxt);
    add(infoMsgPanel);

    Panel onSuccessMsgPanel = new VerticalPanel();
    Panel onSuccessMsgTitelPanel = new HorizontalPanel();
    onSuccessMsgTitelPanel.add(new Label("On Success Message"));
    Image onSuccessMsgInfo = new Image(ServiceUserPlugin.RESOURCES.info());
    onSuccessMsgInfo.setTitle(
        "HTML formatted message that should be"
            + " displayed after a service user was successfully created.");
    onSuccessMsgTitelPanel.add(onSuccessMsgInfo);
    onSuccessMsgTitelPanel.add(new Label(":"));
    onSuccessMsgPanel.add(onSuccessMsgTitelPanel);
    onSuccessMsgTxt = new TextArea();
    onSuccessMsgTxt.setValue(info.getOnSuccessMessage());
    onSuccessMsgTxt.addKeyPressHandler(
        new KeyPressHandler() {
          @Override
          public void onKeyPress(final KeyPressEvent event) {
            event.stopPropagation();
          }
        });
    onSuccessMsgTxt.setVisibleLines(12);
    onSuccessMsgTxt.setCharacterWidth(80);
    onSuccessMsgTxt.getElement().setPropertyBoolean("spellcheck", false);
    onSuccessMsgPanel.add(onSuccessMsgTxt);
    add(onSuccessMsgPanel);

    Panel allowEmailPanel = new HorizontalPanel();
    allowEmailCheckBox = new CheckBox("Allow Email Address");
    allowEmailCheckBox.setValue(info.getAllowEmail());
    allowEmailPanel.add(allowEmailCheckBox);
    Image allowEmailInfo = new Image(ServiceUserPlugin.RESOURCES.info());
    allowEmailInfo.setTitle(
        "Whether it is allowed to provide an email address "
            + "for a service user. E.g. having an email address allows a service user "
            + "to push commits and tags.");
    allowEmailPanel.add(allowEmailInfo);
    add(allowEmailPanel);

    Panel allowHttpPasswordPanel = new HorizontalPanel();
    allowHttpPasswordCheckBox = new CheckBox("Allow HTTP password");
    allowHttpPasswordCheckBox.setValue(info.getAllowHttpPassword());
    allowHttpPasswordPanel.add(allowHttpPasswordCheckBox);
    Image allowHttpPasswordInfo = new Image(ServiceUserPlugin.RESOURCES.info());
    allowHttpPasswordInfo.setTitle(
        "Whether it is allowed to generate an HTTP password "
            + "for a service user. E.g. having an HTTP password allows a service user "
            + "to use the Gerrit REST API.");
    allowHttpPasswordPanel.add(allowHttpPasswordInfo);
    add(allowHttpPasswordPanel);

    Panel allowOwnerPanel = new HorizontalPanel();
    allowOwnerCheckBox = new CheckBox("Allow Owner Group");
    allowOwnerCheckBox.setValue(info.getAllowOwner());
    allowOwnerPanel.add(allowOwnerCheckBox);
    Image allowOwnerInfo = new Image(ServiceUserPlugin.RESOURCES.info());
    allowOwnerInfo.setTitle("Whether it is allowed to set an owner group " + "for a service user.");
    allowOwnerPanel.add(allowOwnerInfo);
    add(allowOwnerPanel);

    Panel createNotesPanel = new HorizontalPanel();
    createNotesCheckBox = new CheckBox("Create Git Notes");
    createNotesCheckBox.setValue(info.getCreateNotes());
    createNotesPanel.add(createNotesCheckBox);
    Image createNotesInfo = new Image(ServiceUserPlugin.RESOURCES.info());
    createNotesInfo.setTitle(
        "Whether commits of a service user should be "
            + "annotated by a Git note that contains information about the current "
            + "owners of the service user. This allows to find a real person that "
            + "is responsible for this commit. To get such a Git note for each commit "
            + "of a service user the 'Forge Committer' access right must be blocked "
            + "for service users.");
    createNotesPanel.add(createNotesInfo);
    add(createNotesPanel);

    Panel createNotesAsyncPanel = new HorizontalPanel();
    createNotesAsyncCheckBox = new CheckBox("Create Git Notes Asynchronously");
    createNotesAsyncCheckBox.setValue(info.getCreateNotesAsync());
    createNotesAsyncCheckBox.setEnabled(info.getCreateNotes());
    createNotesAsyncPanel.add(createNotesAsyncCheckBox);
    Image createNotesAsyncInfo = new Image(ServiceUserPlugin.RESOURCES.info());
    createNotesAsyncInfo.setTitle(
        "Whether the Git notes on commits that are "
            + "pushed by a service user should be created asynchronously.");
    createNotesAsyncPanel.add(createNotesAsyncInfo);
    add(createNotesAsyncPanel);

    createNotesCheckBox.addValueChangeHandler(
        new ValueChangeHandler<Boolean>() {
          @Override
          public void onValueChange(ValueChangeEvent<Boolean> event) {
            createNotesAsyncCheckBox.setEnabled(event.getValue());
          }
        });

    saveButton = new Button("Save");
    saveButton.addStyleName("serviceuser-saveButton");
    saveButton.addClickHandler(
        new ClickHandler() {
          @Override
          public void onClick(final ClickEvent event) {
            doSave();
          }
        });

    blockedUsernamesPanel =
        new StringListPanel("Blocked Usernames", "Username", info.getBlockedNames(), saveButton);
    blockedUsernamesPanel.setInfo(
        "List of usernames which are "
            + "forbidden to be used as name for a service user. "
            + "The blocked usernames are case insensitive.");
    add(blockedUsernamesPanel);

    groupsPanel =
        new StringListPanel("Groups", "Group Name", info.getGroups().keySet(), saveButton);
    groupsPanel.setInfo(
        "Names of groups to which newly created " + "service users should be added automatically.");
    add(groupsPanel);

    HorizontalPanel buttons = new HorizontalPanel();
    add(buttons);

    buttons.add(saveButton);
    saveButton.setEnabled(false);
    OnEditEnabler onEditEnabler = new OnEditEnabler(saveButton, infoMsgTxt);
    onEditEnabler.listenTo(onSuccessMsgTxt);
    onEditEnabler.listenTo(allowEmailCheckBox);
    onEditEnabler.listenTo(allowHttpPasswordCheckBox);
    onEditEnabler.listenTo(allowOwnerCheckBox);
    onEditEnabler.listenTo(createNotesCheckBox);
    onEditEnabler.listenTo(createNotesAsyncCheckBox);

    infoMsgTxt.setFocus(true);
    saveButton.setEnabled(false);
  }

  private void doSave() {
    ConfigInfo in = ConfigInfo.create();
    in.setInfoMessage(infoMsgTxt.getValue());
    in.setOnSuccessMessage(onSuccessMsgTxt.getValue());
    in.setAllowEmail(allowEmailCheckBox.getValue());
    in.setAllowHttpPassword(allowHttpPasswordCheckBox.getValue());
    in.setAllowOwner(allowOwnerCheckBox.getValue());
    in.setCreateNotes(createNotesCheckBox.getValue());
    if (createNotesAsyncCheckBox.isEnabled()) {
      in.setCreateNotesAsync(createNotesAsyncCheckBox.getValue());
    }
    in.setBlockedNames(blockedUsernamesPanel.getValues());
    in.setGroups(groupsPanel.getValues());
    new RestApi("config")
        .id("server")
        .view(Plugin.get().getPluginName(), "config")
        .put(
            in,
            new AsyncCallback<JavaScriptObject>() {

              @Override
              public void onSuccess(JavaScriptObject result) {
                saveButton.setEnabled(false);
              }

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