// 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 net.codemirror.lib;

import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gwt.core.client.Callback;
import com.google.gwt.core.client.ScriptInjector;
import com.google.gwt.dom.client.ScriptElement;
import com.google.gwt.dom.client.StyleInjector;
import com.google.gwt.resources.client.ExternalTextResource;
import com.google.gwt.resources.client.ResourceCallback;
import com.google.gwt.resources.client.ResourceException;
import com.google.gwt.resources.client.TextResource;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.user.client.rpc.AsyncCallback;

import net.codemirror.addon.Addons;
import net.codemirror.keymap.Keymap;

import java.util.logging.Level;
import java.util.logging.Logger;

class Loader {
  private static native boolean isLibLoaded()
  /*-{ return $wnd.hasOwnProperty('CodeMirror'); }-*/;

  static void initLibrary(AsyncCallback<Void> cb) {
    if (isLibLoaded()) {
      cb.onSuccess(null);
    } else {
      CallbackGroup group = new CallbackGroup();
      injectCss(Lib.I.css());
      injectCss(Addons.I.dialogCss());
      injectScript(Lib.I.js().getSafeUri(),
          group.add(CallbackGroup.<Void>emptyCallback()));
      injectScript(Keymap.I.vim().getSafeUri(),
          group.add(CallbackGroup.<Void>emptyCallback()));
      injectScript(Addons.I.dialog().getSafeUri(),
          group.add(CallbackGroup.<Void>emptyCallback()));
      injectScript(Addons.I.searchcursor().getSafeUri(),
          group.add(CallbackGroup.<Void>emptyCallback()));
      injectScript(Addons.I.search().getSafeUri(),
          group.add(CallbackGroup.<Void>emptyCallback()));
      injectScript(Addons.I.mark_selection().getSafeUri(),
          group.add(CallbackGroup.<Void>emptyCallback()));
      injectScript(Addons.I.trailingspace().getSafeUri(),
          group.addFinal(cb));
    }
  }

  private static void injectCss(ExternalTextResource css) {
    try {
      css.getText(new ResourceCallback<TextResource>() {
        @Override
        public void onSuccess(TextResource resource) {
          StyleInjector.inject(resource.getText());
        }

        @Override
        public void onError(ResourceException e) {
          error(e);
        }
      });
    } catch (ResourceException e) {
      error(e);
    }
  }

  static void injectScript(SafeUri js, final AsyncCallback<Void> callback) {
    final ScriptElement[] script = new ScriptElement[1];
    script[0] = ScriptInjector.fromUrl(js.asString())
      .setWindow(ScriptInjector.TOP_WINDOW)
      .setCallback(new Callback<Void, Exception>() {
        @Override
        public void onSuccess(Void result) {
          script[0].removeFromParent();
          callback.onSuccess(result);
        }

        @Override
        public void onFailure(Exception reason) {
          error(reason);
          callback.onFailure(reason);
        }
       })
      .inject()
      .cast();
  }

  private static void error(Exception e) {
    Logger log = Logger.getLogger("net.codemirror");
    log.log(Level.SEVERE, "Cannot load portions of CodeMirror", e);
  }

  private Loader() {
  }
}

@@ -682,16 +682,68 @@
 kGroup;%0A
+import com.google.gerrit.client.rpc.GerritCallback;%0A
 import c
@@ -770,32 +770,32 @@
 lient.Callback;%0A
-
 import com.googl
@@ -1537,16 +1537,22 @@
 Library(
+final 
 AsyncCal
@@ -1637,57 +1637,8 @@
 e %7B%0A
-      CallbackGroup group = new CallbackGroup();%0A
     
@@ -1749,74 +1749,163 @@
 i(),
-%0A          group.add(CallbackGroup.%3CVoid%3EemptyCallback()));%0A
+ new GerritCallback%3CVoid%3E()%7B%0A        @Override%0A        public void onSuccess(Void result) %7B%0A          CallbackGroup group = new CallbackGroup();%0A   
       
+ 
 inje
@@ -1934,32 +1934,36 @@
 ).getSafeUri(),%0A
+    
           group.
@@ -2003,32 +2003,36 @@
 back()));%0A      
+ 
+   
 injectScript(Add
@@ -2062,32 +2062,36 @@
 ri(),%0A          
+   
+ 
 group.add(Callba
@@ -2115,32 +2115,36 @@
 tyCallback()));%0A
+    
       injectScri
@@ -2186,32 +2186,36 @@
 ri(),%0A          
+ 
+   
 group.add(Callba
@@ -2245,32 +2245,36 @@
 back()));%0A      
+   
+ 
 injectScript(Add
@@ -2294,32 +2294,36 @@
 ).getSafeUri(),%0A
+    
           group.
@@ -2363,32 +2363,36 @@
 back()));%0A      
+ 
+   
 injectScript(Add
@@ -2430,32 +2430,36 @@
 ri(),%0A          
+   
+ 
 group.add(Callba
@@ -2487,24 +2487,28 @@
 llback()));%0A
+    
       inject
@@ -2555,32 +2555,36 @@
 ri(),%0A          
+ 
+   
 group.addFinal(c
@@ -2584,24 +2584,44 @@
 Final(cb));%0A
+        %7D%0A      %7D);%0A
     %7D%0A  %7D%0A%0A 

Fix Loader callback