// Copyright (C) 2013 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.api;

import com.google.gerrit.client.ErrorDialog;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.VoidResult;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.Natives;
import com.google.gwt.core.client.Callback;
import com.google.gwt.core.client.CodeDownloadException;
import com.google.gwt.core.client.ScriptInjector;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwtexpui.progress.client.ProgressBar;

import java.util.List;

/** Loads JavaScript plugins with a progress meter visible. */
public class PluginLoader extends DialogBox {
  private static final int MAX_LOAD_TIME_MILLIS = 5000;
  private static PluginLoader self;

  public static void load(List<String> plugins,
      AsyncCallback<VoidResult> callback) {
    if (plugins == null || plugins.isEmpty()) {
      callback.onSuccess(VoidResult.create());
    } else {
      self = new PluginLoader(callback);
      self.load(plugins);
      self.startTimers();
      self.center();
    }
  }

  static void loaded() {
    self.loadedOne();
  }

  private final AsyncCallback<VoidResult> callback;
  private ProgressBar progress;
  private Timer show;
  private Timer update;
  private Timer timeout;
  private boolean visible;

  private PluginLoader(AsyncCallback<VoidResult> cb) {
    super(/* auto hide */false, /* modal */true);
    callback = cb;
    progress = new ProgressBar(Gerrit.C.loadingPlugins());

    setStyleName(Gerrit.RESOURCES.css().errorDialog());
    addStyleName(Gerrit.RESOURCES.css().loadingPluginsDialog());
  }

  private void load(List<String> pluginUrls) {
    for (String url : pluginUrls) {
      Plugin plugin = Plugin.create(url);
      plugins().put(url, plugin);
      ScriptInjector.fromUrl(url)
        .setWindow(ScriptInjector.TOP_WINDOW)
        .setCallback(new LoadCallback(plugin))
        .inject();
    }
  }

  private void startTimers() {
    show = new Timer() {
      @Override
      public void run() {
        setText(Window.getTitle());
        setWidget(progress);
        setGlassEnabled(true);
        getGlassElement().addClassName(Gerrit.RESOURCES.css().errorDialogGlass());
        hide(true);
        center();
        visible = true;
      }
    };
    show.schedule(500);

    update = new Timer() {
      private int cycle;

      @Override
      public void run() {
        progress.setValue(100 * ++cycle * 250 / MAX_LOAD_TIME_MILLIS);
      }
    };
    update.scheduleRepeating(250);

    timeout = new Timer() {
      @Override
      public void run() {
        finish();
      }
    };
    timeout.schedule(MAX_LOAD_TIME_MILLIS);
  }

  private void loadedOne() {
    boolean done = true;
    for (Plugin plugin : Natives.asList(plugins().values())) {
      done &= plugin.loaded();
    }
    if (done) {
      finish();
    }
  }

  private void finish() {
    show.cancel();
    update.cancel();
    timeout.cancel();
    self = null;

    if (!hadFailures()) {
      if (visible) {
        progress.setValue(100);
        new Timer() {
          @Override
          public void run() {
            hide(true);
          }
        }.schedule(250);
      } else {
        hide(true);
      }
    }

    callback.onSuccess(VoidResult.create());
  }

  private boolean hadFailures() {
    boolean failed = false;
    for (Plugin plugin : Natives.asList(plugins().values())) {
      if (!plugin.success()) {
        failed = true;

        Exception e = plugin.failure();
        String msg;
        if (e != null && e instanceof CodeDownloadException) {
          msg = Gerrit.M.cannotDownloadPlugin(plugin.url());
        } else {
          msg = Gerrit.M.pluginFailed(plugin.name());
        }
        hide(true);
        new ErrorDialog(msg).center();
      }
    }
    return failed;
  }

  private static native NativeMap<Plugin> plugins()
  /*-{ return $wnd.Gerrit.plugins }-*/;

  private class LoadCallback implements Callback<Void, Exception> {
    private final Plugin plugin;

    LoadCallback(Plugin plugin) {
      this.plugin = plugin;
    }

    @Override
    public void onSuccess(Void result) {
    }

    @Override
    public void onFailure(Exception reason) {
      plugin.failure(reason);
      loadedOne();
    }
  }
}
