// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.
(function($, cloudStack, require) {
  if (!cloudStack.pluginAPI) {
    cloudStack.pluginAPI = {};
  }

  var loadCSS = function(path) {
    var $link = $('<link>');

    $link.attr({
      rel: 'stylesheet',
      type: 'text/css',
      href: path
    });

    $('head').append($link);
  };

  $.extend(cloudStack.pluginAPI, {
    ui: {
      pollAsyncJob: pollAsyncJobResult,
      apiCall: function(command, args) {
        $.ajax({
          url: createURL(command),
          data: args.data,
          success: args.success,
          error: function(json) {
            args.error(parseXMLHttpResponse(json));
          }
        });
      },
      addSection: function(section) {
        cloudStack.sections[section.id] = $.extend(section, {
          customIcon: 'plugins/' + section.id + '/icon.png'
        });
      },
      extend: function(obj) {
        $.extend(true, cloudStack, obj);
      }
    }
  });
  
  cloudStack.sections.plugins = {
    title: 'label.plugins',
    show: cloudStack.uiCustom.pluginListing
  };

  // Load
  $(['modules', 'plugins']).each(function() {
    var type = this;
    var paths = $(cloudStack[type]).map(function(index, id) {
      return type + '/' + id + '/' + id;
    }).toArray();

    // Load modules
    require(
      paths,
      function() {
        $(cloudStack[type]).map(function(index, id) {
          var basePath = type + '/' + id + '/';
          var css = basePath + id + '.css';
          var configJS = type == 'plugins' ? basePath + 'config' : null;

          if (configJS) {
            // Load config metadata
            require([configJS]);
          }

          // Execute module
          cloudStack[type][id](
            $.extend(true, {}, cloudStack.pluginAPI, {
              pluginAPI: {
                extend: function(api) {
                  cloudStack.pluginAPI[id] = api;
                }
              }
            })
          );
          loadCSS(css);
        });
      }
    );
  });
}(jQuery, cloudStack, require));
