// Copyright (C) 2008 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.google.gerrit.client.account;

import com.google.gerrit.client.ErrorDialog;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.info.AccountInfo;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.ui.OnEditEnabler;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.client.AccountFieldName;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.globalkey.client.NpTextBox;
import com.google.gwtexpui.user.client.AutoCenterDialogBox;

class ContactPanelShort extends Composite {
  protected final FlowPanel body;
  protected int labelIdx;
  protected int fieldIdx;
  protected Button save;

  private String currentEmail;
  protected boolean haveAccount;
  private boolean haveEmails;

  NpTextBox nameTxt;
  private ListBox emailPick;
  private Button registerNewEmail;
  private OnEditEnabler onEditEnabler;

  ContactPanelShort() {
    body = new FlowPanel();
    initWidget(body);
  }

  protected void onInitUI() {
    if (LocaleInfo.getCurrentLocale().isRTL()) {
      labelIdx = 1;
      fieldIdx = 0;
    } else {
      labelIdx = 0;
      fieldIdx = 1;
    }

    nameTxt = new NpTextBox();
    nameTxt.setVisibleLength(60);
    nameTxt.setReadOnly(!canEditFullName());

    emailPick = new ListBox();

    final Grid infoPlainText = new Grid(2, 2);
    infoPlainText.setStyleName(Gerrit.RESOURCES.css().infoBlock());
    infoPlainText.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock());

    body.add(infoPlainText);

    registerNewEmail = new Button(Util.C.buttonOpenRegisterNewEmail());
    registerNewEmail.setEnabled(false);
    registerNewEmail.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        doRegisterNewEmail();
      }
    });
    final FlowPanel emailLine = new FlowPanel();
    emailLine.add(emailPick);
    if (canRegisterNewEmail()) {
      emailLine.add(registerNewEmail);
    }

    int row = 0;
    if (!Gerrit.info().auth().canEdit(AccountFieldName.USER_NAME)
        && Gerrit.info().auth().siteHasUsernames()) {
      infoPlainText.resizeRows(infoPlainText.getRowCount() + 1);
      row(infoPlainText, row++, Util.C.userName(), new UsernameField());
    }

    if (!canEditFullName()) {
      FlowPanel nameLine = new FlowPanel();
      nameLine.add(nameTxt);
      if (Gerrit.info().auth().editFullNameUrl() != null) {
        Button edit = new Button(Util.C.linkEditFullName());
        edit.addClickHandler(new ClickHandler() {
          @Override
          public void onClick(ClickEvent event) {
            Window.open(Gerrit.info().auth().editFullNameUrl(), "_blank", null);
          }
        });
        nameLine.add(edit);
      }
      Button reload = new Button(Util.C.linkReloadContact());
      reload.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(ClickEvent event) {
          Window.Location.replace(Gerrit.loginRedirect(PageLinks.SETTINGS_CONTACT));
        }
      });
      nameLine.add(reload);
      row(infoPlainText, row++, Util.C.contactFieldFullName(), nameLine);
    } else {
      row(infoPlainText, row++, Util.C.contactFieldFullName(), nameTxt);
    }
    row(infoPlainText, row++, Util.C.contactFieldEmail(), emailLine);

    infoPlainText.getCellFormatter().addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
    infoPlainText.getCellFormatter().addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
    infoPlainText.getCellFormatter().addStyleName(row - 1, 0, Gerrit.RESOURCES.css().bottomheader());

    save = new Button(Util.C.buttonSaveChanges());
    save.setEnabled(false);
    save.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        doSave();
      }
    });

    emailPick.addChangeHandler(new ChangeHandler() {
      @Override
      public void onChange(final ChangeEvent event) {
        final int idx = emailPick.getSelectedIndex();
        final String v = 0 <= idx ? emailPick.getValue(idx) : null;
        if (Util.C.buttonOpenRegisterNewEmail().equals(v)) {
          for (int i = 0; i < emailPick.getItemCount(); i++) {
            if (currentEmail.equals(emailPick.getValue(i))) {
              emailPick.setSelectedIndex(i);
              break;
            }
          }
          doRegisterNewEmail();
        } else {
          save.setEnabled(true);
        }
      }
    });

    onEditEnabler = new OnEditEnabler(save, nameTxt);
  }

  private boolean canEditFullName() {
    return Gerrit.info().auth().canEdit(AccountFieldName.FULL_NAME);
  }

  private boolean canRegisterNewEmail() {
    return Gerrit.info().auth().canEdit(AccountFieldName.REGISTER_NEW_EMAIL);
  }

  void hideSaveButton() {
    save.setVisible(false);
  }

  @Override
  protected void onLoad() {
    super.onLoad();

    onInitUI();
    body.add(save);
    display(Gerrit.getUserAccount());

    emailPick.clear();
    emailPick.setEnabled(false);
    registerNewEmail.setEnabled(false);

    haveAccount = false;
    haveEmails = false;

    CallbackGroup group = new CallbackGroup();
    AccountApi.getName("self", group.add(new GerritCallback<NativeString>() {

      @Override
      public void onSuccess(NativeString result) {
        nameTxt.setText(result.asString());
        haveAccount = true;
      }

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

    AccountApi.getEmails("self", group.addFinal(new GerritCallback<JsArray<EmailInfo>>() {
      @Override
      public void onSuccess(JsArray<EmailInfo> result) {
        for (EmailInfo i : Natives.asList(result)) {
          emailPick.addItem(i.email());
          if (i.isPreferred()) {
            currentEmail = i.email();
          }
        }
        haveEmails = true;
        postLoad();
      }
    }));
  }

  private void postLoad() {
    if (haveAccount && haveEmails) {
      updateEmailList();
      registerNewEmail.setEnabled(true);
      save.setEnabled(false);
      onEditEnabler.updateOriginalValue(nameTxt);
    }
    display();
  }

  void display() {
  }

  protected void row(final Grid info, final int row, final String name,
      final Widget field) {
    info.setText(row, labelIdx, name);
    info.setWidget(row, fieldIdx, field);
    info.getCellFormatter().addStyleName(row, 0, Gerrit.RESOURCES.css().header());
  }

  protected void display(AccountInfo account) {
    currentEmail = account.email();
    nameTxt.setText(account.name());
    save.setEnabled(false);
    onEditEnabler.updateOriginalValue(nameTxt);
  }

  private void doRegisterNewEmail() {
    if (!canRegisterNewEmail()) {
      return;
    }

    final AutoCenterDialogBox box = new AutoCenterDialogBox(true, true);
    final VerticalPanel body = new VerticalPanel();

    final NpTextBox inEmail = new NpTextBox();
    inEmail.setVisibleLength(60);

    final Button register = new Button(Util.C.buttonSendRegisterNewEmail());
    final Button cancel = new Button(Util.C.buttonCancel());
    final FormPanel form = new FormPanel();
    form.addSubmitHandler(new FormPanel.SubmitHandler() {
      @Override
      public void onSubmit(final SubmitEvent event) {
        event.cancel();
        final String addr = inEmail.getText().trim();
        if (!addr.contains("@")) {
          new ErrorDialog(Util.C.invalidUserEmail()).center();
          return;
        }

        inEmail.setEnabled(false);
        register.setEnabled(false);
        AccountApi.registerEmail("self", addr, new GerritCallback<EmailInfo>() {
          @Override
          public void onSuccess(EmailInfo result) {
            box.hide();
            if (Gerrit.info().auth().isDev()) {
              currentEmail = addr;
              if (emailPick.getItemCount() == 0) {
                AccountInfo me = Gerrit.getUserAccount();
                me.email(addr);
                onSaveSuccess(me);
              } else {
                save.setEnabled(true);
              }
              updateEmailList();
            }
          }

          @Override
          public void onFailure(final Throwable caught) {
            inEmail.setEnabled(true);
            register.setEnabled(true);
            if (caught.getMessage().startsWith(EmailException.MESSAGE)) {
              final ErrorDialog d =
                  new ErrorDialog(caught.getMessage().substring(
                      EmailException.MESSAGE.length()));
              d.setText(Util.C.errorDialogTitleRegisterNewEmail());
              d.center();
            } else {
              super.onFailure(caught);
            }
          }
        });
      }
    });
    form.setWidget(body);

    register.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        form.submit();
      }
    });
    cancel.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        box.hide();
      }
    });

    final FlowPanel buttons = new FlowPanel();
    buttons.setStyleName(Gerrit.RESOURCES.css().patchSetActions());
    buttons.add(register);
    buttons.add(cancel);

    if (!Gerrit.info().auth().isDev()) {
      body.add(new HTML(Util.C.descRegisterNewEmail()));
    }
    body.add(inEmail);
    body.add(buttons);

    box.setText(Util.C.titleRegisterNewEmail());
    box.setWidget(form);
    box.center();
    inEmail.setFocus(true);
  }

  void doSave() {
    final String newName;
    String name = canEditFullName() ? nameTxt.getText() : null;
    if (name != null && name.trim().isEmpty()) {
      newName = null;
    } else {
      newName = name;
    }

    final String newEmail;
    if (emailPick.isEnabled() && emailPick.getSelectedIndex() >= 0) {
      final String v = emailPick.getValue(emailPick.getSelectedIndex());
      if (Util.C.buttonOpenRegisterNewEmail().equals(v)) {
        newEmail = currentEmail;
      } else {
        newEmail = v;
      }
    } else {
      newEmail = currentEmail;
    }

    save.setEnabled(false);
    registerNewEmail.setEnabled(false);

    CallbackGroup group = new CallbackGroup();
    if (!newEmail.equals(currentEmail)) {
      AccountApi.setPreferredEmail("self", newEmail,
          group.add(new GerritCallback<NativeString>() {
        @Override
        public void onSuccess(NativeString result) {
        }
      }));
    }
    AccountApi.setName("self", newName,
        group.add(new GerritCallback<NativeString>() {
      @Override
      public void onSuccess(NativeString result) {
      }

      @Override
      public void onFailure(Throwable caught) {
        save.setEnabled(true);
        registerNewEmail.setEnabled(true);
        super.onFailure(caught);
      }
    }));
    group.done();
    group.addListener(new GerritCallback<Void>() {
      @Override
      public void onSuccess(Void result) {
        currentEmail = newEmail;
        AccountInfo me = Gerrit.getUserAccount();
        me.email(currentEmail);
        me.name(newName);
        onSaveSuccess(me);
        registerNewEmail.setEnabled(true);
      }
    });
  }

  void onSaveSuccess(AccountInfo result) {
    AccountInfo me = Gerrit.getUserAccount();
    me.name(result.name());
    me.email(result.email());
    Gerrit.refreshMenuBar();
    display(me);
  }

  private int emailListIndexOf(String value) {
    for (int i = 0; i < emailPick.getItemCount(); i++) {
      if (value.equalsIgnoreCase(emailPick.getValue(i))) {
        return i;
      }
    }
    return -1;
  }

  private void updateEmailList() {
    if (currentEmail != null) {
      int index = emailListIndexOf(currentEmail);
      if (index == -1) {
        emailPick.addItem(currentEmail);
        emailPick.setSelectedIndex(emailPick.getItemCount() - 1);
      } else {
        emailPick.setSelectedIndex(index);
      }
    }
    if (emailPick.getItemCount() > 0) {
      if (currentEmail == null) {
        int index = emailListIndexOf("");
        if (index != -1) {
          emailPick.removeItem(index);
        }
        emailPick.insertItem("", 0);
        emailPick.setSelectedIndex(0);
      }
      emailPick.setVisible(true);
      emailPick.setEnabled(true);
      if (canRegisterNewEmail()) {
        final String t = Util.C.buttonOpenRegisterNewEmail();
        int index = emailListIndexOf(t);
        if (index != -1) {
          emailPick.removeItem(index);
        }
        emailPick.addItem("... " + t + "  ", t);
      }
    } else {
      emailPick.setVisible(false);
    }
  }
}
