// Copyright (C) 2009 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.auth.userpass;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.SignInDialog;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.SmallHeading;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.auth.SignInMode;
import com.google.gerrit.common.auth.userpass.LoginResult;
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.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwtexpui.globalkey.client.GlobalKey;
import com.google.gwtexpui.globalkey.client.NpTextBox;

public class UserPassSignInDialog extends SignInDialog {
  static {
    UserPassResources.I.css().ensureInjected();
  }

  private final FlowPanel formBody;

  private FlowPanel errorLine;
  private InlineLabel errorMsg;

  private Button login;
  private Button close;
  private TextBox username;
  private TextBox password;

  public UserPassSignInDialog(final String token, final String initialErrorMsg) {
    super(SignInMode.SIGN_IN, token);
    setAutoHideEnabled(false);

    formBody = new FlowPanel();
    formBody.setStyleName(UserPassResources.I.css().loginForm());
    add(formBody);

    createHeaderText();
    createErrorBox();
    createUsernameBox();
    if (initialErrorMsg != null) {
      showError(initialErrorMsg);
    }
  }

  @Override
  public void show() {
    super.show();
    DeferredCommand.addCommand(new Command() {
      @Override
      public void execute() {
        username.setFocus(true);
      }
    });
  }

  private void createHeaderText() {
    final FlowPanel headerText = new FlowPanel();
    final SmallHeading headerLabel = new SmallHeading();
    headerLabel.setText(Util.M.signInAt(Location.getHostName()));
    headerText.add(headerLabel);
    formBody.add(headerText);
  }

  private void createErrorBox() {
    errorLine = new FlowPanel();
    DOM.setStyleAttribute(errorLine.getElement(), "visibility", "hidden");
    errorLine.setStyleName(UserPassResources.I.css().error());

    errorMsg = new InlineLabel();
    errorLine.add(errorMsg);
    formBody.add(errorLine);
  }

  private void showError(final String msgText) {
    errorMsg.setText(msgText);
    DOM.setStyleAttribute(errorLine.getElement(), "visibility", "");
  }

  private void hideError() {
    DOM.setStyleAttribute(errorLine.getElement(), "visibility", "hidden");
  }

  private void createUsernameBox() {
    username = new NpTextBox();
    username.setVisibleLength(25);
    username.addKeyPressHandler(new KeyPressHandler() {
      @Override
      public void onKeyPress(final KeyPressEvent event) {
        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
          event.preventDefault();
          password.selectAll();
          password.setFocus(true);
        }
      }
    });

    password = new PasswordTextBox();
    password.setVisibleLength(25);
    password.addKeyPressHandler(GlobalKey.STOP_PROPAGATION);
    password.addKeyPressHandler(new KeyPressHandler() {
      @Override
      public void onKeyPress(final KeyPressEvent event) {
        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
          event.preventDefault();
          onLogin();
        }
      }
    });

    final FlowPanel buttons = new FlowPanel();
    buttons.setStyleName(Gerrit.RESOURCES.css().errorDialogButtons());

    login = new Button();
    login.setText(Util.C.buttonSignIn());
    login.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        onLogin();
      }
    });
    buttons.add(login);

    close = new Button();
    close.setText(Gerrit.C.signInDialogClose());
    close.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        hide();
      }
    });
    buttons.add(close);

    final Grid formGrid = new Grid(3, 2);
    formGrid.setText(0, 0, Util.C.username());
    formGrid.setText(1, 0, Util.C.password());
    formGrid.setWidget(0, 1, username);
    formGrid.setWidget(1, 1, password);
    formGrid.setWidget(2, 1, buttons);
    formBody.add(formGrid);

    username.setTabIndex(1);
    password.setTabIndex(2);
    login.setTabIndex(3);
    close.setTabIndex(4);
  }

  private void enable(final boolean on) {
    username.setEnabled(on);
    password.setEnabled(on);
    login.setEnabled(on);
  }

  private void onLogin() {
    hideError();

    final String user = username.getText();
    if (user == null || user.equals("")) {
      showError(Util.C.usernameRequired());
      username.setFocus(true);
      return;
    }

    final String pass = password.getText();
    if (pass == null || pass.equals("")) {
      showError(Util.C.passwordRequired());
      password.setFocus(true);
      return;
    }

    enable(false);
    Util.SVC.authenticate(user, pass, new GerritCallback<LoginResult>() {
      public void onSuccess(final LoginResult result) {
        if (result.success) {
          String to = token;
          if (result.isNew && !to.startsWith(PageLinks.REGISTER + ",")) {
            to = PageLinks.REGISTER + "," + to;
          }

          // Unfortunately we no longer support updating the web UI when the
          // user signs in. Instead we must force a reload of the page, but
          // that isn't easy because we might need to change the anchor. So
          // we bounce through a little redirection servlet on the server.
          //
          Location.replace(Location.getPath() + "login/" + to);
        } else {
          showError(Util.C.invalidLogin());
          enable(true);
          password.selectAll();
          DeferredCommand.addCommand(new Command() {
            @Override
            public void execute() {
              password.setFocus(true);
            }
          });
        }
      }

      @Override
      public void onFailure(final Throwable caught) {
        super.onFailure(caught);
        enable(false);
      }
    });
  }
}
