// Copyright (C) 2015 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.emoticons.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.VerticalPanel;

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

  private CheckBox showEmoticonsBox;
  private Button saveButton;

  protected EmoticonsConfigScreen(RestApi restApi) {
    this.restApi = restApi;
    setStyleName("emoticons-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("emoticons-label-panel");
    showEmoticonsBox = new CheckBox("Show emoticons as images");
    showEmoticonsBox.setValue(info.showEmoticons());
    p.add(showEmoticonsBox);
    Image stageInfo = new Image(EmoticonsPlugin.RESOURCES.lightbulb());
    stageInfo.setTitle("Emoticons in comments are replaced by images.");
    p.add(stageInfo);
    add(p);

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

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

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

  private void doSave() {
    ConfigInfo in = ConfigInfo.create();
    in.setShowEmoticons(showEmoticonsBox.getValue());
    restApi.put(
        in,
        new AsyncCallback<JavaScriptObject>() {
          @Override
          public void onSuccess(JavaScriptObject result) {
            saveButton.setEnabled(false);
            onSave();
          }

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

  protected void onSave() {}
}
