/**
 * repo.js
 * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd. All rights reserved.
 *
 * Contact:
 * Sungmin Kim <sm.art.kim@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 path = require('path');
var _ = require('underscore');
// var util = require('util');

var DError = require('../../core/exception.js');
var Distribution = require('./distribution.js');

// repo based on filesystem
var fsRepo = require('./lib/fs-repo-api.js');
var webRepo = require('./lib/web-repo-api.js');

module.exports = TizenRepository;

function TizenRepository(config) {
    this.path = config.path;
    this.url = config.url;
    this.isRemoteRepo = config.isRemoteRepo || false;
    this.distributions = {};
}

TizenRepository.prototype.isRepositoryExist = isRepositoryExist;
TizenRepository.prototype.open = open;
TizenRepository.prototype.close = close;
TizenRepository.prototype.createDistribution = createDistribution;
TizenRepository.prototype.removeDistribution = removeDistribution;
TizenRepository.prototype.searchDistributions = searchDistributions;


function isRepositoryExist(callback) {
    var self = this;

    // check distribution.info
    if (self.isRemoteRepo) {
        //TODO:
    } else {
        fsRepo.isRepositoryExist(self.path, callback);
    }
}


function open(callback) {
    var self = this;

    async.waterfall([
        function (cb) {
            if (self.isRemoteRepo) {
                var repoUrl = path.dirname(self.url.href);
                webRepo.loadDistributions(repoUrl, self.distName, function (err, dists) {
                    cb(err, dists);
                });
            } else {
                fsRepo.loadDistributions(self.path, null, function (err, dists) {
                    cb(err, dists);
                });
            }
        },
        function (dists, cb) {
            async.each(dists, function (dist, cb1) {
                var distribution = new Distribution(dist.name, dist.path, {});
                distribution.time = dist.time;
                self.distributions[dist.name] = distribution;

                distribution.loadSnapshots(cb1);
            },
            function (err) {
                cb(err);
            });
        }
    ],
    function (err) {
        callback(err);
    });
}


function close(callback) {
    /*
     * NOTE. Do nothing.
     */ 
    callback(null);
}


function createDistribution(name, opts, callback) {
    var self = this;

    if (self.isRemoteRepo) {
        callback(new DError('TREPO002'), null);
        return;
    }

    // check
    if (self.distributions[name] !== undefined) {
        callback(new DError('TREPO005', { dist: name }), null);
        return;
    }

    // Distribution.create(name, opts, self.path, callback);
    var tsDist = new Distribution(name, path.join(self.path, name), {});

    fsRepo.createDistribution(self, tsDist, function (err) {
        if (!err) {
            self.distributions[name] = tsDist;
        }
        callback(err);
    });
}


function removeDistribution(name, opts, callback) {
    var self = this;

    if (self.isRemoteRepo) {
        callback(new DError('TREPO002'), null);
        return;
    }

    if (!self.distributions[name]) {
        callback(new DError('TREPO004', { dist: name }), null);
        return;
    }

    fsRepo.removeDistribution(name, self.path, function (err) {
        if (err) {
            // TODO: should handle errors.
        } else {
            // remove if distribution files are removed successfully
            delete self.distributions[name];
        }
        callback(err);
    });

    // remove distOptions & synchronization in config.yaml
    // removeDistributionOptionsToConfig(name);
    // removeSyncToConfig(name);
}


function searchDistributions(opts, callback) {
    var self = this;
    var distName = null;

    if (_.isString(opts)) {
        distName = opts;
        opts = { distName: distName };
    } else if (opts.distName) {
        distName = opts.distName;
    } else {
        // do nothing
    }


    if (self.isRemoteRepo) {
        var options = {};
        if (opts.snapshotName) {
            options.snapshotName = opts.snapshotName;
        }
        webRepo.loadDistributions(self.url, distName, options, callback);
    } else {
        var dists = _.where(self.distributions, opts);
        return callback(null, dists);
    }
}
