/**
 * ts-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
**/

'use strict';

var async = require('async');
var fs = require('fs');
var path = require('path');
var url = require('url');

var DError = require('../../core/exception.js');
var Distribution = require('./distribution.js');
var fsRepo = require('../org.tizen.ts.base.repository/lib/fs-repo-api.js');
var TizenRepository = require('../org.tizen.ts.base.repository/repo.js');
var utils = require('../../lib/utils.js');
var webRepo = require('../org.tizen.ts.base.repository/lib/web-repo-api.js');

module.exports = TsRepository;

function TsRepository(config) {
    TizenRepository.call(this, config);

    var self = this;
    self.config = config || {};

    if (config && config.location) {
        if (utils.isURL(config.location)) {
            self.isRemoteRepo = true;
            self.url = url.parse(config.location);
            self.distName = path.basename(self.url.pathname);
        } else {
            self.path = path.dirname(path.normalize(path.resolve(config.location)));
            self.distName = path.basename(path.normalize(config.location));
        }
    }
}

// inherit Repository
TsRepository.prototype = Object.create(TizenRepository.prototype);
TsRepository.constructor = TsRepository;

TsRepository.prototype.createDistribution = function (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);
    });
};

TsRepository.prototype.open = function (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, dists);
            });
        },
        function (dists, cb) {
            async.each(dists, function (dist, cb1) {
                var lockFile = path.join(dist.path, '.lock');
                fs.access(lockFile, function (err) {
                    if (err) {
                        cb(null);
                    } else {
                        fs.unlink(lockFile, cb);
                    }
                });
            }, function (err) {
                cb(err);
            });
        }
    ],
    function (err) {
        callback(err);
    });
};

TsRepository.prototype.load = function (callback) {
    var self = this;

    async.waterfall([
        function (cb) {
            if (self.isRemoteRepo) {
                cb(null, true);
            } else {
                // check if a distribution exists or not.
                self.isRepositoryExist(function (exists) {
                    if (exists) {
                        fs.access(path.join(self.path, self.distName), function (err) {
                            if (err) {
                                exists = false;
                            }
                            cb(null, exists);
                        });
                    } else {
                        cb(null, exists);
                    }
                });
            }
        },
        function (exists, cb) {
            if (exists) {
                cb(null);
            } else {
                self.createDistribution(self.distName, {}, function (err) {
                    callback(err);
                });
            }
        },
        function (cb) {
            self.open(function (err) {
                cb(err);
            });
        }
    ], function (err) {
        callback(err);
    });
};

