// 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.imagare.client;

import com.google.gerrit.plugin.client.rpc.RestApi;
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.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.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public abstract class ImagareConfigScreen extends VerticalPanel {
  private final RestApi restApi;

  private TextBox projectBox;
  private ListBox linkDecorationBox;
  private CheckBox stageBox;
  private Button saveButton;

  protected ImagareConfigScreen(RestApi restApi) {
    this.restApi = restApi;
    setStyleName("imagare-config-screen");
    restApi.get(new AsyncCallback<ConfigInfo>() {
        @Override
        public void onSuccess(ConfigInfo info) {
          display(info);
        }

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

  protected void display(ConfigInfo info) {
    HorizontalPanel p = new HorizontalPanel();
    p.setStyleName("imagare-label-panel");
    p.add(new Label("Project"));
    Image projectInfo = new Image(ImagarePlugin.RESOURCES.info());
    projectInfo.setTitle("The default project for the image upload.");
    p.add(projectInfo);
    p.add(new Label(":"));
    projectBox = new TextBox();
    projectBox.setValue(info.getDefaultProject());
    p.add(projectBox);
    add(p);

    p = new HorizontalPanel();
    p.setStyleName("imagare-label-panel");
    p.add(new Label("Link Decoration"));
    Image linkDecorationInfo = new Image(ImagarePlugin.RESOURCES.info());
    linkDecorationInfo.setTitle("Decoration for image links in the Gerrit WebUI."
        + " 'NONE': no decoration, 'TOOLTIP': the image is shown as tooltip on"
        + " mouse over an image link, 'INLINE': the image is inlined instead of"
        + " the URL.");
    p.add(linkDecorationInfo);
    p.add(new Label(":"));
    linkDecorationBox = new ListBox();
    int i = 0;
    for (LinkDecoration v : LinkDecoration.values()) {
      linkDecorationBox.addItem(v.name());
      if (v.equals(info.getLinkDecoration())) {
        linkDecorationBox.setSelectedIndex(i);
      }
      i++;
    }
    p.add(linkDecorationBox);
    add(p);

    p = new HorizontalPanel();
    p.setStyleName("imagare-label-panel");
    stageBox = new CheckBox("Stage images before upload");
    stageBox.setValue(info.stage());
    p.add(stageBox);
    Image stageInfo = new Image(ImagarePlugin.RESOURCES.info());
    stageInfo.setTitle("Images are not uploaded immediately but put into a "
        + "staging area. The upload must be triggered explicitely.");
    p.add(stageInfo);
    add(p);

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

    saveButton = new Button("Save");
    saveButton.setStyleName("imagare-save-button");
    saveButton.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        doSave();
      }
    });
    buttons.add(saveButton);
    saveButton.setEnabled(false);
    OnEditEnabler onEditEnabler = new OnEditEnabler(saveButton, projectBox);
    onEditEnabler.listenTo(linkDecorationBox);
    onEditEnabler.listenTo(stageBox);

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

  private void doSave() {
    ConfigInfo in = ConfigInfo.create();
    in.setDefaultProject(projectBox.getValue());
    in.setLinkDecoration(linkDecorationBox.getValue(linkDecorationBox.getSelectedIndex()));
    in.setStage(stageBox.getValue());
    restApi.put(in, new AsyncCallback<JavaScriptObject>() {
        @Override
        public void onSuccess(JavaScriptObject result) {
          saveButton.setEnabled(false);
        }

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