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

import com.google.gerrit.plugin.client.Plugin;
import com.google.gerrit.plugin.client.extension.Panel;
import com.google.gerrit.plugin.client.rpc.RestApi;
import com.google.gwt.dom.client.Style.Unit;
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.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public class LabelUiPreferencesPanel extends VerticalPanel {
  static class Factory implements Panel.EntryPoint {
    @Override
    public void onLoad(Panel panel) {
      panel.setWidget(new LabelUiPreferencesPanel());
    }
  }

  LabelUiPreferencesPanel() {
    new RestApi("accounts").id("self")
        .view(Plugin.get().getPluginName(), "preferences")
        .get(new AsyncCallback<PreferencesInfo>() {
          @Override
          public void onSuccess(PreferencesInfo result) {
            display(result);
          }

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

  private void display(PreferencesInfo info) {
    Label heading = new Label(Plugin.get().getName() + " plugin");
    heading.setStyleName("smallHeading");
    add(heading);
    HorizontalPanel p = new HorizontalPanel();
    add(p);

    Label label = new Label("Label UI:");
    p.add(label);
    label.getElement().getStyle().setMarginRight(5, Unit.PX);
    label.getElement().getStyle().setMarginTop(2, Unit.PX);
    final ListBox ui = new ListBox();
    p.add(ui);

    for (PreferencesInfo.LabelUi v : PreferencesInfo.LabelUi.values()) {
      ui.addItem(v.name(), v.name());
    }

    for (int i = 0; i < ui.getItemCount(); i++) {
      if (info.ui().name().equals(ui.getValue(i))) {
        ui.setSelectedIndex(i);
        break;
      }
    }

    ui.addChangeHandler(new ChangeHandler() {
      @Override
      public void onChange(ChangeEvent event) {
        PreferencesInfo info = PreferencesInfo.create();
        info.ui(ui.getSelectedValue());
        new RestApi("accounts").id("self")
            .view(Plugin.get().getPluginName(), "preferences")
            .put(info, new AsyncCallback<PreferencesInfo>() {
              @Override
              public void onSuccess(PreferencesInfo result) {
              }

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