// 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.openid;

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.auth.SignInMode;
import com.google.gerrit.common.auth.openid.DiscoveryResult;
import com.google.gerrit.common.auth.openid.OpenIdProviderPattern;
import com.google.gerrit.common.auth.openid.OpenIdUrls;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.FormElement;
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.resources.client.ImageResource;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
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.FormSubmitCompleteEvent;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwtexpui.globalkey.client.NpTextBox;

import java.util.Map;

public class OpenIdSignInDialog extends SignInDialog implements
    FormPanel.SubmitHandler {
  static {
    OpenIdResources.I.css().ensureInjected();
  }

  private final FlowPanel panelWidget;
  private final FormPanel form;
  private final FlowPanel formBody;
  private final FormPanel redirectForm;
  private final FlowPanel redirectBody;

  private FlowPanel errorLine;
  private InlineLabel errorMsg;

  private Button login;
  private NpTextBox providerId;
  private CheckBox rememberId;
  private boolean discovering;

  public OpenIdSignInDialog(final SignInMode requestedMode, final String token,
      final String initialErrorMsg) {
    super(requestedMode, token);

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

    form = new FormPanel();
    form.setMethod(FormPanel.METHOD_GET);
    form.addSubmitHandler(this);
    form.add(formBody);

    redirectBody = new FlowPanel();
    redirectBody.setVisible(false);
    redirectForm = new FormPanel();
    redirectForm.add(redirectBody);

    panelWidget = new FlowPanel();
    panelWidget.add(form);
    panelWidget.add(redirectForm);
    add(panelWidget);

    createHeaderLogo();
    createHeaderText();
    createErrorBox();
    createIdentBox();

    link(OpenIdUrls.URL_GOOGLE, OpenIdUtil.C.nameGoogle(), OpenIdResources.I
        .iconGoogle());
    link(OpenIdUrls.URL_YAHOO, OpenIdUtil.C.nameYahoo(), OpenIdResources.I
        .iconYahoo());

    if (initialErrorMsg != null) {
      showError(initialErrorMsg);
    }
    formBody.add(new HTML(OpenIdUtil.C.whatIsOpenIDHtml()));
  }

  @Override
  public void show() {
    super.show();
    providerId.selectAll();
    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
      @Override
      public void execute() {
        providerId.setFocus(true);
      }
    });
  }

  private void createHeaderLogo() {
    final FlowPanel headerLogo = new FlowPanel();
    headerLogo.setStyleName(OpenIdResources.I.css().logo());
    headerLogo.add(new Image(OpenIdResources.I.openidLogo()));
    formBody.add(headerLogo);
  }

  private void createHeaderText() {
    final FlowPanel headerText = new FlowPanel();
    final String me = Window.Location.getHostName();
    final SmallHeading headerLabel = new SmallHeading();
    switch (mode) {
      case LINK_IDENTIY:
        headerLabel.setText(OpenIdUtil.M.linkAt(me));
        break;
      case REGISTER:
        headerLabel.setText(OpenIdUtil.M.registerAt(me));
        break;
      case SIGN_IN:
      default:
        headerLabel.setText(OpenIdUtil.M.signInAt(me));
        break;
    }
    headerText.add(headerLabel);
    formBody.add(headerText);
  }

  private void createErrorBox() {
    errorLine = new FlowPanel();
    DOM.setStyleAttribute(errorLine.getElement(), "visibility", "hidden");
    errorLine.setStyleName(OpenIdResources.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 createIdentBox() {
    boolean remember = mode == SignInMode.SIGN_IN || mode == SignInMode.REGISTER;

    final FlowPanel group = new FlowPanel();
    group.setStyleName(OpenIdResources.I.css().loginLine());

    final FlowPanel line1 = new FlowPanel();
    group.add(line1);

    providerId = new NpTextBox();
    providerId.setVisibleLength(60);
    providerId.setStyleName(OpenIdResources.I.css().identifier());
    providerId.setTabIndex(0);
    providerId.addKeyPressHandler(new KeyPressHandler() {
      @Override
      public void onKeyPress(final KeyPressEvent event) {
        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
          event.preventDefault();
          form.submit();
        }
      }
    });
    line1.add(providerId);

    login = new Button();
    switch (mode) {
      case LINK_IDENTIY:
        login.setText(OpenIdUtil.C.buttonLinkId());
        break;
      case REGISTER:
        login.setText(OpenIdUtil.C.buttonRegister());
        break;
      case SIGN_IN:
      default:
        login.setText(OpenIdUtil.C.buttonSignIn());
        break;
    }
    login.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        form.submit();
      }
    });
    login.setTabIndex(remember ? 2 : 1);
    line1.add(login);

    Button close = new Button(Gerrit.C.signInDialogClose());
    close.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        hide();
      }
    });
    close.setTabIndex(remember ? 3 : 2);
    line1.add(close);

    if (remember) {
      rememberId = new CheckBox(OpenIdUtil.C.rememberMe());
      rememberId.setTabIndex(1);
      group.add(rememberId);

      String last = Cookies.getCookie(OpenIdUrls.LASTID_COOKIE);
      if (last != null && !"".equals(last)) {
        if (last.startsWith("\"") && last.endsWith("\"")) {
          // Dequote the value. We shouldn't have to do this, but
          // something is causing some Google Account tokens to get
          // wrapped up in double quotes when obtained from the cookie.
          //
          last = last.substring(1, last.length() - 2);
        }
        providerId.setText(last);
        rememberId.setValue(true);
      }
    }

    formBody.add(group);
  }

  private void link(final String identUrl, final String who,
      final ImageResource icon) {
    if (!isAllowedProvider(identUrl)) {
      return;
    }

    final ClickHandler i = new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        event.preventDefault();
        if (!discovering) {
          providerId.setText(identUrl);
          form.submit();
        }
      }
    };

    final FlowPanel line = new FlowPanel();
    line.addStyleName(OpenIdResources.I.css().directLink());

    final Image img = new Image(icon);
    img.addClickHandler(i);
    line.add(img);

    final Anchor text = new Anchor();
    switch (mode) {
      case LINK_IDENTIY:
        text.setText(OpenIdUtil.M.linkWith(who));
        break;
      case REGISTER:
        text.setText(OpenIdUtil.M.registerWith(who));
        break;
      case SIGN_IN:
      default:
        text.setText(OpenIdUtil.M.signInWith(who));
        break;
    }
    text.setHref(identUrl);
    text.addClickHandler(i);
    line.add(text);

    formBody.add(line);
  }

  private static boolean isAllowedProvider(final String identUrl) {
    for (OpenIdProviderPattern p : Gerrit.getConfig().getAllowedOpenIDs()) {
      if (p.matches(identUrl)) {
        return true;
      }
    }
    return false;
  }

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

  private void onDiscovery(final DiscoveryResult result) {
    discovering = false;

    switch (result.status) {
      case VALID:
        // The provider won't support operation inside an IFRAME,
        // so we replace our entire application.
        //
        redirectForm.setMethod(FormPanel.METHOD_POST);
        redirectForm.setAction(result.providerUrl);
        redirectBody.clear();
        for (final Map.Entry<String, String> e : result.providerArgs.entrySet()) {
          redirectBody.add(new Hidden(e.getKey(), e.getValue()));
        }
        FormElement.as(redirectForm.getElement()).setTarget("_top");
        redirectForm.submit();
        break;

      case NOT_ALLOWED:
        showError(OpenIdUtil.C.notAllowed());
        enableRetryDiscovery();
        break;

      case NO_PROVIDER:
        showError(OpenIdUtil.C.noProvider());
        enableRetryDiscovery();
        break;

      case ERROR:
      default:
        showError(OpenIdUtil.C.error());
        enableRetryDiscovery();
        break;
    }
  }

  private void enableRetryDiscovery() {
    enable(true);
    providerId.selectAll();
    providerId.setFocus(true);
  }

  @Override
  public void onSubmit(final SubmitEvent event) {
    event.cancel();

    String openidIdentifier = providerId.getText();
    if (openidIdentifier == null || openidIdentifier.equals("")) {
      enable(true);
      return;
    }

    if (!openidIdentifier.startsWith("http://")
        && !openidIdentifier.startsWith("https://")) {
      openidIdentifier = "http://" + openidIdentifier;
    }

    if (!isAllowedProvider(openidIdentifier)) {
      showError(OpenIdUtil.C.notAllowed());
      enableRetryDiscovery();
      return;
    }

    discovering = true;
    enable(false);
    hideError();

    final boolean remember = rememberId != null && rememberId.getValue();
    OpenIdUtil.SVC.discover(openidIdentifier, mode, remember, token,
        new GerritCallback<DiscoveryResult>() {
          public void onSuccess(final DiscoveryResult result) {
            onDiscovery(result);
          }

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

  public void onSubmitComplete(final FormSubmitCompleteEvent event) {
  }
}
