/**
 * pkg-svr.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
**/

var async = require('async');
var fork = require('child_process').fork;
var yaml = require('js-yaml');
var fs = require('fs');
var extfs = require('fs-extra');
var optimist = require('optimist');
var os = require('os');
var path = require('path');
var readline = require('readline');
var _ = require('underscore');

var dibs = require('../../../core/dibs.js');
var tizenUtil = require('../../org.tizen.common/tizen_utils.js');

// get host information
var host = tizenUtil.getTargetOS(os.platform(), os.arch());

// option parse & set
var argv = optimist.usage(
    'Usage: pkg-svr SUBCOMMAND [OPTS] or $0 (-h|-v)' + os.EOL +
    'Subcommands:' + os.EOL +
    '    create          Create a package-server.' + os.EOL +
    '    remove          Remove a package-server.' + os.EOL +
    '    start           Start the package-server.' + os.EOL +
    '    stop            Stop the package-server.' + os.EOL +
    '    add-dist        Add a distribution to package-server.' + os.EOL +
    '    remove-dist     Remove a distribution to package-server.' + os.EOL +
    '    add-pkg         Register a package in package-server.' + os.EOL +
    '    remove-pkg      Remove a package in package-server.' + os.EOL +
    '    list-snapshot   Show a list of snapshot in package-server.' + os.EOL +
    '    add-snapshot    Generate a snapshot in package-server.' + os.EOL +
    '    remove-snapshot Remove a snapshot in package-server.' + os.EOL +
    '    sync            Synchronize the package-server from parent package server.' + os.EOL +
    os.EOL +
    'Subcommand usage:' + os.EOL +
    '    pkg-svr create -n <server name> [-l <location>] ' + os.EOL +
    '    pkg-svr remove -n <server name> ' + os.EOL +
    '    pkg-svr start -n <server name> -p <port>' + os.EOL +
    '    pkg-svr stop -n <server name>' + os.EOL +
    '    pkg-svr add-dist -n <server name> -d <distribution> [-u <remote server url>]' + os.EOL +
    '    pkg-svr remove-dist -n <server name> -d <distribution>' + os.EOL +
    '    pkg-svr add-pkg -n <server name> -d <distribution> -P <package file list>' + os.EOL +
    '    pkg-svr remove-pkg -n <server name> -d <distribution> -P <package name list> [-o <os>] ' + os.EOL +
    '    pkg-svr list-snapshot -n <server name> -d <distribution> ' + os.EOL +
    '    pkg-svr add-snapshot -n <server name> -d <distribution> -s <snapshot name> [-b <base snapshot name>] ' + os.EOL +
    '    pkg-svr remove-snapshot -n <server name> -d <distribution> [-s <snapshot name list>] [-t <filter type>] ' + os.EOL +
    '    pkg-svr sync -n <server name> -d <distribution> [-u <remote server url>] [-s <snapshot name>] [--force] ' + os.EOL +
    '    pkg-svr add-sync -n <server name> -d <distribution> [-u <remote server url>] [-i <sync period time>] ' + os.EOL
).alias({n: 'name', d: 'dist', u: 'url', o: 'os', P: 'pkgs', s: 'snapshot', b: 'base',
        l: 'loc', p: 'port', t: 'type', f: 'force', i: 'interval', h: 'help'})
    .string(['n', 'd', 'u', 'o', 'P', 's', 'b', 'l'])
    .describe('n', 'package server name')
    .describe('d', 'package server distribution')
    .describe('u', 'remote package server url: http://download.tizen.org/sdk/latest/tizen')
    .describe('o', 'os information')
    .describe('P', 'package file path list')
    .describe('s', 'snapshot name or snapshot list')
    .describe('b', 'base snapshot name')
    .describe('l', 'server location')
    .describe('p', 'port')
    .describe('t', 'types of removing snapshots: basic/exclude/all')
    .describe('i', 'distribution synchronization for the specified number of seconds.')
    .describe('f', 'force synchronization')
    .describe('h', 'display help')
    .default('t', 'basic')
    .default('o', host.os.toString())
    .default('i', '600')
    .argv;

var subCmds = argv._;

if (argv.h) {
    optimist.showHelp();
    process.exit(0);
}

if (!subCmds || subCmds.length === 0) {
    console.error('Sub-Command must be specified!');
    optimist.showHelp();
    process.exit(-1);
}

// init variables
var serverName = argv.n;
var distName = argv.d;
var remoteUrl = argv.u;
var osName = argv.o;
var pkgListString = argv.P;
var snapshotName = argv.s;
var baseSnapshotName = argv.b;
var serverLocation = argv.l;
var port = parseInt(argv.p, 10);
var filterType = argv.t;
var distSyncPeriod = argv.i;
var forceSync = argv.f;

switch (subCmds[0]) {
case 'create':
    handle_create_command(serverName, serverLocation);
    break;
case 'remove':
    handle_remove_command(serverName);
    break;
case 'start':
    handle_start_command(serverName, port);
    break;
case 'stop':
    handle_stop_command(serverName);
    break;
case 'add-dist':
    handle_add_dist_command(serverName, distName, remoteUrl);
    break;
case 'remove-dist':
    handle_remove_dist_command(serverName, distName);
    break;
case 'add-pkg':
    handle_add_pkg_command(serverName, distName, pkgListString);
    break;
case 'remove-pkg':
    handle_remove_pkg_command(serverName, distName, pkgListString, osName);
    break;
case 'list-snapshot':
    handle_list_snapshot_command(serverName, distName);
    break;
case 'add-snapshot':
    handle_add_snapshot_command(serverName, distName, snapshotName, baseSnapshotName);
    break;
case 'remove-snapshot':
    handle_remove_snapshot_command(serverName, distName, snapshotName, filterType);
    break;
case 'sync':
    handle_sync_command(serverName, distName, remoteUrl, snapshotName, forceSync);
    break;
case 'add-sync':
    handle_add_sync_command(serverName, distName, remoteUrl, distSyncPeriod);
    break;
default:
    console.error('Invalid sub-command!: \'' + subCmds[0] + '\'');
    process.exit(-1);
}


function handle_create_command(serverName, serverLocation) {
    var dibsConfigDir;
    var masterServerName;
    var masterServerConfigDir;
    var repoServerConfigDir;
    var serverConfigFile;

    async.waterfall([
        function (cb) {
            dibs.initialize();
            dibsConfigDir = dibs.config.getConfigDir();
            // check arguments
            if (!serverName || serverName.length === 0) {
                cb(new Error('Server name MUST be specified!'));
            } else {
                masterServerName = serverName + '.master';
                cb(null);
            }
        },
        function (cb) {
            // check if server directories already exists
            repoServerConfigDir = path.join(dibsConfigDir, serverName);
            fs.exists(repoServerConfigDir, function (exists) {
                if (exists) {
                    cb(new Error('The server name \'' + serverName + '\'(' + repoServerConfigDir + ') already exists!'));
                } else {
                    // create server directories
                    if (!serverLocation) {
                        serverLocation = path.join(repoServerConfigDir, 'repository');
                    }
                    extfs.mkdirpSync(repoServerConfigDir);
                    cb(null);
                }
            });
        },
        function (cb) {
            // check if server directories already exists
            masterServerConfigDir = path.join(dibsConfigDir, masterServerName);
            fs.exists(masterServerConfigDir, function (exists) {
                if (exists) {
                    cb(new Error('The server name \'' + masterServerName + '\'(' + masterServerConfigDir + ') already exists!'));
                } else {
                    // create server directories
                    extfs.mkdirpSync(masterServerConfigDir);
                    cb(null);
                }
            });
        },
        function (cb) {
            // create server directories
            if (fs.existsSync(serverLocation)) {
                // set read-line interface
                var readLine = readline.createInterface({
                    input: process.stdin,
                    output: process.stdout
                });

                readLine.question('The repository directory(' + serverLocation +
                    ') alreay exists! Would you clean it? (Y/N)', function (answer) {
                    if (answer === 'Y') {
                        extfs.removeSync(serverLocation);
                        extfs.mkdirpSync(serverLocation);
                        cb(null);
                    } else {
                        cb(new Error('Cancel repository creation'));
                    }
                    readLine.close();
                });
            } else {
                extfs.mkdirpSync(serverLocation);
                cb(null);
            }
        },
        function (cb) {
            // create repo server config file
            serverConfigFile = path.join(repoServerConfigDir, 'config.yaml');
            fs.writeFileSync(serverConfigFile, 'repo_path: \'' + serverLocation + '\'' + os.EOL);
            fs.appendFileSync(serverConfigFile, 'web_port: ' + 80 + os.EOL);
            fs.appendFileSync(serverConfigFile, 'dfs-path: \'' + path.join(repoServerConfigDir, 'share') + '\'' + os.EOL);
            fs.appendFileSync(serverConfigFile, 'dfs-size: ' + (1024 * 1024 * 1024 * 10) + os.EOL); // 10G
            fs.appendFileSync(serverConfigFile, 'log_file: \'' + path.join(repoServerConfigDir, 'log') + '\'' + os.EOL);
            cb(null);
        }
    ], function (err) {
        if (err) {
            console.error(err.message);
            process.exit(-1);
        } else {
            console.log('The package server \'' + serverName + '\' is created successfully!');
        }
    });
}


function handle_remove_command(serverName) {

    // check arguments
    if (!serverName || serverName.length === 0) {
        console.error('Server name MUST be specified!');
        process.exit(-1);
    }

    dibs.initialize();
    var dibsConfigDir = dibs.config.getConfigDir();

    // get repository path
    var repoServerConfigDir = path.join(dibsConfigDir, serverName);
    var repoServerConfigFile = path.join(repoServerConfigDir, 'config.yaml');
    var repoPath = yaml.safeLoad(fs.readFileSync(repoServerConfigFile, 'utf-8')).repo_path;

    // check if server directories already exists
    var masterServerName = serverName + '.master';
    var masterServerConfigDir = path.join(dibsConfigDir, masterServerName);
    if (!fs.existsSync(masterServerConfigDir)) {
        console.error('The server name ' + masterServerName + ' does not exists!');
        process.exit(-1);
    }

    // remove config directories
    extfs.removeSync(masterServerConfigDir);
    extfs.removeSync(repoServerConfigDir);


    // check if repository directory will be removed
    if (fs.existsSync(repoPath)) {
        // set read-line interface
        var readLine = readline.createInterface({
            input: process.stdin,
            output: process.stdout
        });

        readLine.question('The repository directory(' + repoPath +
        ') remains unremoved! Would you clean it? (Y/N)', function (answer) {
            if (answer === 'Y') {
                extfs.removeSync(repoPath);
            }
            readLine.close();
            console.log('The package server \'' + serverName + '\' is removed successfully!');
        });
    } else {
        console.log('The package server \'' + serverName + '\' is removed successfully!');
    }
}


function handle_start_command(serverName, port) {

    // check arguments
    if (!serverName || serverName.length === 0) {
        console.error('Server name MUST be specified!');
        process.exit(-1);
    }
    if (isNaN(port)) {
        console.error('Port option(-p) MUST be specified!');
        process.exit(-1);
    }

    dibs.initialize();
    var dibsConfigDir = dibs.config.getConfigDir();
    var masterServerName = serverName + '.master';
    var masterServerConfigDir = path.join(dibsConfigDir, masterServerName);

    // create master server config file
    var serverConfigFile = path.join(masterServerConfigDir, 'config.yaml');
    fs.writeFileSync(serverConfigFile,
        'sub_servers:' + os.EOL +
        ' repo:' + os.EOL +
        '  id: \'' + serverName + '\'' + os.EOL +
        '  host: \'127.0.0.1\'' + os.EOL +
        '  port: ' + port + os.EOL
    );
    fs.appendFileSync(serverConfigFile, 'log_file: \'' + path.join(masterServerConfigDir, 'log') + '\'' + os.EOL);

    var logPath = path.join(masterServerConfigDir, 'out.log');
    if (!fs.existsSync(logPath)) {
        fs.writeFileSync(logPath, '');
    }
    var out = fs.openSync(logPath, 'a');
    var err = fs.openSync(logPath, 'a');

    var child = fork(path.resolve(__dirname, '..', '..', '..', 'app.js'), [
        '-i', masterServerName,
        '-p', (parseInt(port, 10) + 2)
    ], {
        detached: true,
        silent: true
    });

    //child.unref();
    child.stdout.on('data', function (out) {
        if (out.toString().indexOf('Server is READY!') !== -1) {
            console.log('Server is launched successfully!');
            child.unref();
            process.exit(0);
        } else {
            console.log(out.toString());
        }
    });
    child.stderr.on('data', function (err) {
        console.error(err.toString());
        //process.exit(-1);
    });
    child.on('close', function (code) {
        console.error(code);
        process.exit(-1);
    });
}


function handle_stop_command(serverName) {

    // check arguments
    if (!serverName || serverName.length === 0) {
        console.error('Server name MUST be specified!');
        process.exit(-1);
    }

    var servers = loadServers(serverName);

    if (!servers.master) {
        return console.error('Cannot find master server!');
    }

    servers.master.terminateServer(function (err) {
        if (err) {
            console.error(err);
            console.error('Terminating server failed!');
        } else {
            console.log('Server is terminated successfully!');
        }
    });
}


function handle_add_dist_command(serverName, distName, remoteUrl) {

    // check arguments
    if (!serverName || serverName.length === 0) {
        console.error('Server name MUST be specified!');
        process.exit(-1);
    }
    if (!distName || distName.length === 0) {
        console.error('Distribution name MUST be specified!');
        process.exit(-1);
    }

    var servers = loadServers(serverName);

    async.series([
        function (cb) {
            servers.repository.createDistribution(distName, 'tizen', {}, function (err) {
                if (err) {
                    console.error('Creating distribution failed!');
                } else {
                    console.log('Creating distribution succeeded!');
                }
                cb(err);
            });
        },
        function (cb) {
            if (remoteUrl) {
                console.log('Loading distribution from remote URL... ' + distName + '<-' + path.dirname(remoteUrl) + '/' + path.basename(remoteUrl));
                servers.repository.synchronizeDistribution(distName, {
                    repoType: 'tizen',
                    SYNC_URL: path.dirname(remoteUrl),
                    SYNC_DIST_NAME: path.basename(remoteUrl),
                    progress: function (msg) {
                        console.log(msg);
                    }
                }, function (err) {
                    if (err) {
                        console.error('Loading distribution from remote failed!');
                    } else {
                        console.log('Loading distribution from remote succeeded!');
                    }
                    cb(err);
                });
            } else {
                cb(null);
            }
        }
    ], function (err) {
        // TODO
        if (err) {
            console.error(err);
        }
    });
}


function handle_remove_dist_command(serverName, distName) {

    // check arguments
    if (!serverName || serverName.length === 0) {
        console.error('Server name MUST be specified!');
        process.exit(-1);
    }
    if (!distName || distName.length === 0) {
        console.error('Distribution name MUST be specified!');
        process.exit(-1);
    }

    var servers = loadServers(serverName);

    servers.repository.removeDistribution(distName, {
        repoType: 'tizen'
    }, function (err) {
        if (err) {
            console.error(err);
            console.error('Removing distribution failed!');
        } else {
            console.log('Removing distribution succeeded!');
        }
    });
}


function handle_add_pkg_command(serverName, distName, pkgFileList) {

    // check arguments
    if (!serverName || serverName.length === 0) {
        console.error('Server name MUST be specified!');
        process.exit(-1);
    }
    if (!distName || distName.length === 0) {
        console.error('Distribution name MUST be specified!');
        process.exit(-1);
    }
    if (!pkgFileList || pkgFileList.length === 0) {
        console.error('Package file(s) MUST be specified!');
        process.exit(-1);
    }

    // parse package files
    var filePathList = pkgFileList.split(',').map(function (e) {
        if (e.indexOf('.') === 0) {
            return path.resolve(process.cwd(), e);
        } else {
            return path.resolve(e);
        }
    });

    var servers = loadServers(serverName);

    servers.repository.registerPackages(filePathList, {
        repoType: 'tizen',
        distName: distName
    }, function (err) {
        if (err) {
            console.error(err);
            console.error('Registering package(s) failed!');
        } else {
            console.log('Registering packages(s) succeeded!');
        }
    });
}


function handle_remove_pkg_command(serverName, distName, pkgNameList, osName) {

    // check arguments
    if (!serverName || serverName.length === 0) {
        console.error('Server name MUST be specified!');
        process.exit(-1);
    }
    if (!distName || distName.length === 0) {
        console.error('Distribution name MUST be specified!');
        process.exit(-1);
    }
    if (!pkgNameList || pkgNameList.length === 0) {
        console.error('Package name(s) MUST be specified!');
        process.exit(-1);
    }

    if (osName && osName.length === 0) {
        console.error('OS name CANNOT be empty!');
        process.exit(-1);
    }

    // parse package names
    pkgNameList = pkgNameList.split(',');

    validateOsInfo(osName.split(','), function (err, results) {
        if (err) {
            console.error(err);
            console.error('Removing package(s) failed!');
        } else {
            async.eachSeries(results, function (osInfo, cb) {
                var servers = loadServers(serverName);
                var options = {
                    repoType: 'tizen',
                    distName: distName,
                    os: osInfo
                };
                servers.repository.removePackages(pkgNameList, options, function (err) {
                    if (err) {
                        console.error(err);
                        console.error('[' + osInfo + '] Removing package(s) failed!');
                    } else {
                        console.log('[' + osInfo + '] Removing packages(s) succeeded!');
                    }
                    cb(null);
                });
            }, function (err) {
                if (err) {
                    console.error(err);
                }
            });
        }
    });
}


function handle_list_snapshot_command(serverName, distName) {
    // check arguments
    if (!serverName || serverName.length === 0) {
        console.error('Server name MUST be specified!');
        process.exit(-1);
    }
    if (!distName || distName.length === 0) {
        console.error('Distribution name MUST be specified!');
        process.exit(-1);
    }

    var servers = loadServers(serverName);
    servers.repository.searchSnapshots({ repoType: 'tizen', distName: distName, snapshotInfoOnly: true }, function (err, results) {
        if (err) {
            console.error(err);
        } else {
            _.each(results, function (snapshot) {
                console.log(snapshot.name);
            });
        }
    });
}

function handle_add_snapshot_command(serverName, distName, snapshotName, baseSnapshotName) {

    // check arguments
    if (!serverName || serverName.length === 0) {
        console.error('Server name MUST be specified!');
        process.exit(-1);
    }
    if (!distName || distName.length === 0) {
        console.error('Distribution name MUST be specified!');
        process.exit(-1);
    }
    if (!snapshotName || snapshotName.length === 0) {
        console.error('Snapshot name MUST be specified!');
        process.exit(-1);
    } else if (/,/.test(snapshotName)) {
        console.error('\',\' cannot be included in a snapshot name!');
        process.exit(-1);
    }

    var servers = loadServers(serverName);

    var options = {
        repoType: 'tizen',
        distName: distName,
        snapshotType: 'manual'
    };
    if (baseSnapshotName) {
        options.refSnapshot = baseSnapshotName;
    }

    servers.repository.generateSnapshot(snapshotName, options, function (err) {
        if (err) {
            console.error(err);
            console.error('Generating snapshot failed!');
        } else {
            console.log('Generating snapshot succeeded!');
        }
    });
}


function handle_remove_snapshot_command(serverName, distName, snapshotName, filterType) {

    // check arguments
    if (!serverName || serverName.length === 0) {
        console.error('Server name should be given!');
        process.exit(-1);
    }
    if (!distName || distName.length === 0) {
        console.error('Distribution name MUST be specified!');
        process.exit(-1);
    }

    if (!_.contains(['basic', 'exclude', 'all'], filterType)) {
        console.error('Invalid remove type: ' + filterType);
        process.exit(-1);
    }

    if (filterType === 'all' && snapshotName !== undefined) {
        console.error('\'all\' type does not need snapshot name!');
        process.exit(-1);
    } else if (filterType !== 'all' && (!snapshotName || _.isEmpty(snapshotName))) {
        console.error('Snapshot name should be given!');
        process.exit(-1);
    }

    var servers = loadServers(serverName);
    if (snapshotName === undefined) {
        snapshotName = [];
    } else {
        snapshotName = _.uniq(snapshotName.split(','));
    }

    var conditions = {
        repoType: 'tizen',
        distName: distName,
        snapshotInfoOnly: true
    };

    async.waterfall([
        function (cb) {
            servers.repository.searchSnapshots(conditions, function (err, results) {
                if (err) {
                    console.error(err);
                    cb(err);
                } else {
                    if (results.length === 0) {
                        var msg = 'Any snapshots does not exist in ' + distName;
                        cb(new Error(msg));
                    } else {
                        var snapshotList = _.map(results, function (snapshot) {
                            return snapshot.name;
                        });

                        // get all snapshots except latest snapshot.
                        var latestSnapshot = _.last(_.where(results, {type: 'auto'})).name;
                        var remainSnapshots = _.filter(snapshotList, function (name) {
                            return name !== latestSnapshot;
                        });

                        if (filterType === 'basic') {
                            cb(null, snapshotName);
                        } else if (filterType === 'exclude') {
                            // remove all snapshots except given snapshots
                            cb(null, _.difference(remainSnapshots, snapshotName));
                        } else {
                            // remove all snapshots.
                            cb(null, remainSnapshots);
                        }
                    }
                }
            });
        },
        function (newSnapshotName, cb) {
            console.log('a list of snapshot removal');
            console.log(newSnapshotName);

            var opts = _.clone(conditions);
            delete opts.snapshotInfoOnly;
            servers.repository.removeSnapshot(newSnapshotName, opts, cb);
        }
    ],
    function (err) {
        if (err) {
            console.error(err);
            console.error('Removing snapshot failed!');
            process.exit(-1);
        } else {
            console.log('Removing snapshot succeeded!');
        }
    });
}


function handle_sync_command(serverName, distName, remoteUrl, snapshotName, forceSync) {
   // check arguments
    if (!serverName || serverName.length === 0) {
        console.error('Server name MUST be specified!');
        process.exit(-1);
    }
    if (!distName || distName.length === 0) {
        console.error('Distribution name MUST be specified!');
        process.exit(-1);
    }

    var servers = loadServers(serverName);

    var syncOptions = {
        repoType: 'tizen'
    };
    if (remoteUrl) {
        syncOptions.SYNC_METHOD = 'direct';
        syncOptions.SYNC_URL = path.dirname(remoteUrl);
        syncOptions.SYNC_DIST_NAME = path.basename(remoteUrl);
        syncOptions.SYNC_PREFIX = 'sync_';
        syncOptions.SYNC_SNAPSHOT = snapshotName || '';
        syncOptions.progress = function (msg) {
            console.log(msg);
        };
    }

    if (forceSync === true) {
        syncOptions.SYNC_FORCE = forceSync;
    }

    // synchronize
    servers.repository.synchronizeDistribution(distName, syncOptions, function (err) {
        if (err) {
            console.error(err);
            console.error('Synchronizing distribution failed!');
        } else {
            console.log('Synchronizing distribution succeeded!');
        }
    });
}

function handle_add_sync_command(serverName, distName, remoteUrl, periodTime) {
    // check arguments
    if (!serverName || serverName.length === 0) {
        console.error('Server name MUST be specified!');
        process.exit(-1);
    }
    if (!distName || distName.length === 0) {
        console.error('Distribution name MUST be specified!');
        process.exit(-1);
    }

    var servers = loadServers(serverName);

    var syncOptions = {
        repoType: 'tizen'
    };
    if (remoteUrl) {
        syncOptions.SYNC_METHOD = 'direct';
        syncOptions.SYNC_URL = path.dirname(remoteUrl);
        syncOptions.SYNC_DIST_NAME = path.basename(remoteUrl);
        syncOptions.SYNC_PERIOD = periodTime;
    }

    servers.repository.updateDistributionConfig(distName, syncOptions, function (err) {
        if (err) {
            console.error(err);
            console.error('Updating distribution failed!');
        } else {
            console.log('Updating distribution succeeded!');
        }
    });
}


function loadServers(serverName) {
    dibs.initialize();
    var result = {};

    // find repository server
    var dibsConfigDir = dibs.config.getConfigDir();
    var workingPortFile = path.join(dibsConfigDir, serverName, 'PORT');
    if (!fs.existsSync(workingPortFile)) {
        console.error('Server is not working!');
        process.exit(-1);
    }

    var serverType = 'repo';
    var svr = dibs.createServer(serverName, serverType);
    svr.host = '127.0.0.1';
    svr.port = parseInt(fs.readFileSync(workingPortFile), 10);
    dibs.addServer(svr);

    result.repository = dibs.getServer(serverName);

    // find master server
    var masterServerName = serverName + '.master';

    dibsConfigDir = dibs.config.getConfigDir();
    workingPortFile = path.join(dibsConfigDir, masterServerName, 'PORT');

    if (fs.existsSync(workingPortFile)) {
        var masterServer = dibs.createServer(masterServerName, 'master');
        masterServer.host = '127.0.0.1';
        masterServer.port = parseInt(fs.readFileSync(workingPortFile), 10);
        dibs.addServer(masterServer);

        result.master = dibs.getServer(masterServerName);
    }

    return result;
}

function validateOsInfo(input, callback) {
    var tizenOsList = [];
    var osList = [];
    tizenUtil.getOsList('Tizen-Source').forEach(function (osInfo) {
        tizenOsList.push(osInfo);
    });

    var osFlag = true;
    if (input[0] === 'all') {
        osList = tizenOsList;
    } else {
        input.forEach(function (osInfo) {
            if (contains(tizenOsList, osInfo) === -1) {
                osFlag = false;
            } else {
                osList.push(osInfo);
            }
        });
    }
    if (osFlag) {
        callback(null, osList);
    } else {
        callback(new Error('not exists'), null);
    }
}

function contains(array, value) {
    var index = 0;
    for (; index < array.length; index++) {
        if (array[index] === value) {
            return index;
        }
    }
    return -1;
}
