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

import com.google.gerrit.client.SignInDialog;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.SmallHeading;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.FormElement;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FormHandler;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormSubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormSubmitEvent;
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.gwt.user.client.ui.KeyboardListenerAdapter;
import com.google.gwt.user.client.ui.NamedFrame;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtjsonrpc.client.CallbackHandle;

import java.util.Map;

public class OpenIdLoginPanel extends Composite implements FormHandler {
  private final SignInDialog.Mode mode;
  private final CallbackHandle<?> discoveryCallback;
  private final CallbackHandle<?> signInCallback;
  private final LoginIcons icons;
  private final AllowFrameImpl allowFrame;
  private final FlowPanel panelWidget;
  private final FormPanel form;
  private final FlowPanel formBody;
  private final NamedFrame providerFrame;
  private final Hidden discoveryCbField;
  private final Hidden signInCbField;
  private final Hidden providerField;

  private final FormPanel redirectForm;
  private final FlowPanel redirectBody;

  private FlowPanel errorLine;
  private InlineLabel errorMsg;

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

  public OpenIdLoginPanel(final SignInDialog.Mode m, final CallbackHandle<?> sc) {
    mode = m;
    signInCallback = sc;

    discoveryCallback =
        OpenIdUtil.SVC.discover(new GerritCallback<DiscoveryResult>() {
          public void onSuccess(final DiscoveryResult result) {
            onDiscovery(result);
          }
        });
    icons = GWT.create(LoginIcons.class);
    allowFrame = GWT.create(AllowFrameImpl.class);

    formBody = new FlowPanel();
    formBody.setStyleName("gerrit-OpenID-loginform");
    formBody.add(providerField = new Hidden("openid_identifier"));
    formBody.add(signInCbField = new Hidden(OpenIdUtil.P_SIGNIN_CB));
    formBody.add(discoveryCbField = new Hidden(OpenIdUtil.P_DISCOVERY_CB));
    formBody.add(new Hidden(OpenIdUtil.P_SIGNIN_MODE, mode.name()));

    providerFrame = new NamedFrame(DOM.createUniqueId());
    providerFrame.setVisible(false);

    form = new FormPanel(providerFrame);
    form.setMethod(FormPanel.METHOD_GET);
    form.setAction(GWT.getModuleBaseURL() + "login");
    form.addFormHandler(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);
    panelWidget.add(providerFrame);
    initWidget(panelWidget);

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

    link(OpenIdUtil.URL_GOOGLE, OpenIdUtil.C.nameGoogle(), icons.iconGoogle());
    link(OpenIdUtil.URL_YAHOO, OpenIdUtil.C.nameYahoo(), icons.iconYahoo());

    formBody.add(new HTML(OpenIdUtil.C.whatIsOpenIDHtml()));
  }

  public void setFocus(final boolean take) {
    if (take) {
      providerId.selectAll();
    }
    providerId.setFocus(take);
  }

  private void createHeaderLogo() {
    final FlowPanel headerLogo = new FlowPanel();
    headerLogo.setStyleName("gerrit-OpenID-logobox");
    headerLogo.add(icons.openidLogo().createImage());
    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 SIGN_IN:
      default:
        headerLabel.setText(OpenIdUtil.M.signInAt(me));
        break;
    }
    headerText.add(headerLabel);
    formBody.add(headerText);
  }

  private void createErrorBox() {
    errorLine = new FlowPanel();
    errorLine.setVisible(false);

    errorMsg = new InlineLabel(OpenIdUtil.C.notSupported());
    errorLine.setStyleName("gerrit-OpenID-errorline");
    errorLine.add(errorMsg);
    formBody.add(errorLine);
  }

  private void showError() {
    errorLine.setVisible(true);
  }

  private void hideError() {
    errorLine.setVisible(false);
  }

  private void createIdentBox() {
    final FlowPanel group = new FlowPanel();
    group.setStyleName("gerrit-OpenID-loginline");

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

    providerId = new TextBox();
    providerId.setVisibleLength(60);
    providerId.setStyleName("gerrit-OpenID-openid_identifier");
    providerId.setTabIndex(0);
    providerId.addKeyboardListener(new KeyboardListenerAdapter() {
      @Override
      public void onKeyPress(Widget sender, char keyCode, int modifiers) {
        if (keyCode == KEY_ENTER) {
          final Event event = DOM.eventGetCurrentEvent();
          DOM.eventCancelBubble(event, true);
          DOM.eventPreventDefault(event);
          form.submit();
        }
      }
    });
    line1.add(providerId);

    login = new Button();
    switch (mode) {
      case LINK_IDENTIY:
        login.setText(OpenIdUtil.C.buttonLinkId());
        break;
      case SIGN_IN:
      default:
        login.setText(OpenIdUtil.C.buttonSignIn());
        break;
    }
    login.addClickListener(new ClickListener() {
      public void onClick(Widget sender) {
        form.submit();
      }
    });
    login.setTabIndex(2);
    line1.add(login);

    if (mode == SignInDialog.Mode.SIGN_IN) {
      rememberId = new CheckBox(OpenIdUtil.C.rememberMe());
      rememberId.setName(OpenIdUtil.P_REMEMBERID);
      rememberId.setTabIndex(1);
      group.add(rememberId);

      final String last = Cookies.getCookie(OpenIdUtil.LASTID_COOKIE);
      if (last != null && !"".equals(last)) {
        providerId.setText(last);
        rememberId.setChecked(true);
      }
    }

    formBody.add(group);
  }

  private void link(final String identUrl, final String who,
      final AbstractImagePrototype icon) {
    final ClickListener i = new ClickListener() {
      public void onClick(Widget sender) {
        if (!discovering) {
          providerId.setText(identUrl);
          form.submit();
        }
      }
    };

    final FlowPanel line = new FlowPanel();
    line.addStyleName("gerrit-OpenID-directlink");

    final Image img = icon.createImage();
    img.addClickListener(i);
    line.add(img);

    final InlineLabel lbl = new InlineLabel();
    switch (mode) {
      case LINK_IDENTIY:
        lbl.setText(OpenIdUtil.M.linkWith(who));
        break;
      case SIGN_IN:
      default:
        lbl.setText(OpenIdUtil.M.signInWith(who));
        break;
    }
    lbl.addClickListener(i);
    line.add(lbl);

    formBody.add(line);
  }

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

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

    if (result.validProvider) {
      final String url = providerId.getText();

      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()));
      }

      final FormElement fe = FormElement.as(redirectForm.getElement());
      if (allowFrame.permit(url)) {
        // The provider will work OK inside an IFRAME, so use it.
        //
        fe.setTarget(providerFrame.getName());

        // The provider page needs time to load. It won't load as fast as
        // we can update the DOM so we delay our DOM update for just long
        // enough that the provider is likely to be loaded.
        //
        new Timer() {
          @Override
          public void run() {
            panelWidget.remove(form);
            providerFrame.setVisible(true);
          }
        }.schedule(250);
      } else {
        // The provider won't support operation inside an IFRAME, so we
        // replace our entire application. No fancy waits are needed,
        // the browser won't update anything until its started to load
        // the provider's page.
        //
        fe.setTarget("_top");
      }
      redirectForm.submit();

    } else {
      // We failed discovery. We have to use a deferred command here
      // as we are being called from within an invisible IFRAME. Jump
      // back to the main event loop in the parent window.
      //
      DeferredCommand.addCommand(new Command() {
        public void execute() {
          showError();
          enable(true);
          providerId.selectAll();
          providerId.setFocus(true);
        }
      });
    }
  }

  @Override
  protected void onUnload() {
    discoveryCallback.cancel();
    super.onUnload();
  }

  public void onSubmit(final FormSubmitEvent event) {
    final String url = providerId.getText();
    if (url == null || url.equals("")) {
      enable(true);
      event.setCancelled(true);
      return;
    }

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

    discoveryCallback.install();
    discoveryCbField.setValue("parent." + discoveryCallback.getFunctionName());
    providerField.setValue(url);

    if (allowFrame.permit(url)) {
      signInCbField.setValue("parent." + signInCallback.getFunctionName());
    } else {
      // The provider won't work right inside of an IFRAME (or likely isn't
      // going to work within the IFRAME) so we need to replace the whole
      // application and then redirect back to this location.
      //
      signInCbField.setValue("history:" + History.getToken());
    }
  }

  @Override
  public void setWidth(final String width) {
    providerFrame.setWidth(width);
    super.setWidth(width);
  }

  @Override
  public void setHeight(final String height) {
    providerFrame.setHeight(height);
    super.setHeight(height);
  }

  public void onSubmitComplete(final FormSubmitCompleteEvent event) {
  }
}
