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

import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.rpc.RpcConstants;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.StatusCodeException;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtjsonrpc.client.RemoteJsonException;

/** A dialog box showing an error message, when bad things happen. */
public class ErrorDialog extends PopupPanel {
  private final Label text;
  private final FlowPanel body;
  private final Button closey;

  protected ErrorDialog() {
    super(/* auto hide */false, /* modal */true);
    setGlassEnabled(true);
    getGlassElement().addClassName(Gerrit.RESOURCES.css().errorDialogGlass());

    text = new Label();
    text.setStyleName(Gerrit.RESOURCES.css().errorDialogTitle());

    body = new FlowPanel();

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

    closey = new Button();
    closey.setText(Gerrit.C.errorDialogContinue());
    closey.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        hide();
      }
    });
    closey.addKeyPressHandler(new KeyPressHandler() {
      @Override
      public void onKeyPress(KeyPressEvent event) {
        // if the close button is triggered by a key we need to consume the key
        // event, otherwise the key event would be propagated to the parent
        // screen and eventually trigger some unwanted action there after the
        // error dialog was closed
        event.stopPropagation();
      }
    });
    buttons.add(closey);

    final FlowPanel center = new FlowPanel();
    center.add(text);
    center.add(body);
    center.add(buttons);

    setText(Gerrit.C.errorTitle());
    addStyleName(Gerrit.RESOURCES.css().errorDialog());
    add(center);

    int l = Window.getScrollLeft() + 20;
    int t = Window.getScrollTop() + 20;
    setPopupPosition(l, t);
  }

  /** Create a dialog box to show a single message string. */
  public ErrorDialog(final String message) {
    this();
    body.add(new Label(message));
  }

  /** Create a dialog box to show a single message string. */
  public ErrorDialog(final SafeHtml message) {
    this();
    body.add(message.toBlockWidget());
  }

  public ErrorDialog(final Widget w) {
    this();
    body.add(w);
  }

  /** Create a dialog box to nicely format an exception. */
  public ErrorDialog(final Throwable what) {
    this();

    String hdr;
    String msg;

    if (what instanceof StatusCodeException) {
      StatusCodeException sc = (StatusCodeException) what;
      if (RestApi.isExpected(sc.getStatusCode())) {
        hdr = null;
        msg = sc.getEncodedResponse();
      } else if (sc.getStatusCode() == Response.SC_INTERNAL_SERVER_ERROR) {
        hdr = null;
        msg = what.getMessage();
      } else {
        hdr = RpcConstants.C.errorServerUnavailable();
        msg = what.getMessage();
      }

    } else if (what instanceof RemoteJsonException) {
      // TODO Remove RemoteJsonException from Gerrit sources.
      hdr = RpcConstants.C.errorRemoteJsonException();
      msg = what.getMessage();

    } else {
      // TODO Fix callers of ErrorDialog to stop passing random types.
      hdr = what.getClass().getName();
      if (hdr.startsWith("java.lang.")) {
        hdr = hdr.substring("java.lang.".length());
      } else if (hdr.startsWith("com.google.gerrit.")) {
        hdr = hdr.substring(hdr.lastIndexOf('.') + 1);
      }
      if (hdr.endsWith("Exception")) {
        hdr = hdr.substring(0, hdr.length() - "Exception".length());
      } else if (hdr.endsWith("Error")) {
        hdr = hdr.substring(0, hdr.length() - "Error".length());
      }
      msg = what.getMessage();
    }

    if (hdr != null) {
      final Label r = new Label(hdr);
      r.setStyleName(Gerrit.RESOURCES.css().errorDialogErrorType());
      body.add(r);
    }

    if (msg != null) {
      final Label m = new Label(msg);
      m.getElement().getStyle().setProperty("whiteSpace", "pre");
      body.add(m);
    }
  }

  public ErrorDialog setText(final String t) {
    text.setText(t);
    return this;
  }

  @Override
  public void center() {
    show();
    closey.setFocus(true);
  }
}
