// 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.gwt.core.client.JsArrayString;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
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.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusWidget;
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.gwtexpui.globalkey.client.NpTextBox;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class StringListPanel extends FlowPanel {
  private final NpTextBox input;
  private final StringListTable t;
  private final Button deleteButton;
  private final HorizontalPanel titlePanel;
  private Image info;

  StringListPanel(String title, String fieldName, JsArrayString values,
      final FocusWidget w) {
    this(title, fieldName, Natives.asList(values), w);
  }

  StringListPanel(String title, String fieldName, Collection<String> values,
      final FocusWidget w) {
    titlePanel = new HorizontalPanel();
    Label titleLabel = new Label(title);
    titleLabel.setStyleName("serviceuser-smallHeading");
    titlePanel.add(titleLabel);
    add(titlePanel);
    input = new NpTextBox();
    input.addKeyPressHandler(new KeyPressHandler() {
      @Override
      public void onKeyPress(KeyPressEvent event) {
        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
          w.setEnabled(true);
          add();
        }
      }
    });
    HorizontalPanel p = new HorizontalPanel();
    p.add(input);
    Button addButton = new Button("Add");
    addButton.setEnabled(false);
    new OnEditEnabler(addButton, input);
    addButton.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        w.setEnabled(true);
        add();
      }
    });
    p.add(addButton);
    add(p);

    t = new StringListTable(fieldName);
    add(t);

    deleteButton = new Button("Delete");
    deleteButton.setEnabled(false);
    add(deleteButton);
    deleteButton.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        w.setEnabled(true);
        t.deleteChecked();
      }
    });

    t.display(values);
  }

  void setInfo(String msg) {
    if (info == null) {
      info = new Image(ServiceUserPlugin.RESOURCES.info());
      titlePanel.add(info);
    }
    info.setTitle(msg);
  }

  List<String> getValues() {
    return t.getValues();
  }

  private void add() {
    String v = input.getValue().trim();
    if (!v.isEmpty()) {
      input.setValue("");
      t.insert(v);
    }
  }

  private class StringListTable extends FlexTable {
    StringListTable(String name) {
      setStyleName("serviceuser-stringListTable");
      FlexCellFormatter fmt = getFlexCellFormatter();
      fmt.addStyleName(0, 0, "iconHeader");
      fmt.addStyleName(0, 0, "topMostCell");
      fmt.addStyleName(0, 0, "leftMostCell");
      fmt.addStyleName(0, 1, "dataHeader");
      fmt.addStyleName(0, 1, "topMostCell");

      setText(0, 1, name);
    }

    void display(Collection<String> values) {
      int row = 1;
      for (String v : values) {
        populate(row, v);
        row++;
      }
    }

    List<String> getValues() {
      List<String> values = new ArrayList<>();
      for (int row = 1; row < getRowCount(); row++) {
        values.add(getText(row, 1));
      }
      return values;
    }

    private void populate(int row, String value) {
      FlexCellFormatter fmt = getFlexCellFormatter();
      fmt.addStyleName(row, 0, "leftMostCell");
      fmt.addStyleName(row, 0, "iconCell");
      fmt.addStyleName(row, 1, "dataCell");

      CheckBox checkBox = new CheckBox();
      checkBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
        @Override
        public void onValueChange(ValueChangeEvent<Boolean> event) {
          enableDelete();
        }
      });
      setWidget(row, 0, checkBox);
      setText(row, 1, value);
    }

    void insert(String v) {
      int insertPos = getRowCount();
      for (int row = 1; row < getRowCount(); row++) {
        int compareResult = v.compareTo(getText(row, 1));
        if (compareResult < 0)  {
          insertPos = row;
          break;
        } else if (compareResult == 0) {
          return;
        }
      }
      insertRow(insertPos);
      populate(insertPos, v);
    }

    void enableDelete() {
      for (int row = 1; row < getRowCount(); row++) {
        if (((CheckBox) getWidget(row, 0)).getValue()) {
          deleteButton.setEnabled(true);
          return;
        }
      }
      deleteButton.setEnabled(false);
    }

    void deleteChecked() {
      deleteButton.setEnabled(false);
      for (int row = 1; row < getRowCount(); row++) {
        if (((CheckBox) getWidget(row, 0)).getValue()) {
          removeRow(row--);
        }
      }
    }
  }
}
