/**
 * plugin-manager.js
 * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
 *
 * Contact:
 * DongHee Yang <donghee.yang@samsung.com>
 * Sungmin Kim <sm.art.kim@samsung.com>
 * Jiil Hyoun <jiil.hyoun@samsung.com>
 * Jonghwan Park <iwin100.park@samsung.com>
 * Kitae Kim <kt920.kim@samsung.com>
 *
 * 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.
 *
 * Contributors:
 * - S-Core Co., Ltd
**/

define(['dojo/request'], function (request) {

    function WebPluginManager() {

        var plugins = {};
        var activePlugins = {};
        var extensionPoints = {};
        var currentVersion = '0.0.0';
        var availableVersion = '0.0.0';

        // Intialize basic structure by server communication
        this.initialize = function (callback) {
            request.get('dplugins', {
                handleAs: 'json'
            }).then(function (response) {
                currentVersion = response.currentVersion;
                availableVersion = response.availableVersion;
                plugins = response.plugins;
                activePlugins = response.activePlugins;
                extensionPoints = response.extensionPoints;
                callback(null);
            }, function (err) {
                console.log('error:', err);
                callback(err);
            });
        };


        // Get plguins
        this.getPlugins = function () {
            return plugins;
        };


        this.getCurrentVersion = function () {
            return currentVersion;
        };


        this.getAvailableVersion = function () {
            return availableVersion;
        };


        this.getExtensionsInfo = function (expId) {
            var exp = extensionPoints[expId];
            return exp.extensions;
        };

        // Get all extensions from specified extension point
        this.getExtensions = function (expId, callback) {
            var exp = extensionPoints[expId];
            if (exp === undefined || exp === null) {
                callback('Undefined extension point id(\'' + expId + '\') used!', null);
                return;
            }

            async.series([
                // Load plugin if needed
                function (cb) {
                    loadPluginIfNeeded(exp.pluginName, function (err) {
                        cb(err);
                    });
                }],
                // Finally, get extensions
                function (err) {
                    if (err) {
                        callback(err, []);
                    } else {
                        getExtensionsFromExp(exp, callback);
                    }
                });
        };


        // Load initial plugin
        // callback: err, plugin
        this.loadInitialPlugin = function (pluginName, callback) {
            loadPluginIfNeeded(pluginName, callback);
        };


        function getExtensionsFromExp(exp, callback) {
            var exts = exp.extensions;
            async.each(exts,
                // Load plugin if needed
                function (item, cb) {
                    loadPluginIfNeeded(item.pluginName, function (err) {
                        cb(err);
                    });
                },
                function (err) {
                    if (err) {
                        callback(err, []);
                    } else {
                        callback(null, exts);
                    }
                });
        }


        function loadPluginIfNeeded(pluginName, callback) {
            // obj(loaded) or null(checked)
            if (activePlugins[pluginName] !== undefined) {
                callback(null);
                return;
            }

            var plugin = plugins[pluginName];
            if (plugin === undefined) {
                callback('The plugin \'' + pluginName + '\' not found!');
                return;
            }

            // Check me to prevent cyclinic
            activePlugins[pluginName] = null;

            async.series([
                // Load dependent plugin first
                function (cb) {
                    async.each(plugin.deps,
                        function (item, cb1) {
                            loadPluginIfNeeded(item, cb1);
                        },
                        function (err) {
                            cb(err);
                        });
                }],
                // Load me
                function (err) {
                    if (err) {
                        callback(err);
                    } else {
                        if (plugin.type === 'web') {
                            require(['plugins/' + plugin.name + '/activator.js'],
                                function (activator) {
                                    activePlugins[pluginName] = activator;
                                    activator.start(callback);
                                });
                        } else {
                            callback(null);
                        }
                    }
                });
        }
    }

    return new WebPluginManager();
});
