/**
 * Batch to fetch pixabay data.
 * @function serverside.batch.newPixabayDataFetchBatch
 * @param {object} context - Batch contextLoader.
 * @returns {object} - A new batch instance.
 * @author Taka Okunishi
 */
var apeman = require('apeman'),
    path = require('path'),
    fs = require('fs'),
    lib = require('../../lib'),
    file = lib.file,
    writeReadonlyFile = file.writeReadonlyFile,
    mkdirP = file.mkdirP,
    array = lib.array,
    newUniqueFilter = array.newUniqueFilter,
    shuffled = array.shuffled,
    fetch = lib.fetch,
    pixabayApiFetch = fetch.pixabayApiFetch,
    newBatchLogger = require('../logger/new_batch_logger');


exports = module.exports = function (context) {
    context.assertKeys(['PIXABAY_SECRET_FILE_PATH', 'PIXABAY_TAGS_FILE_PATH', 'PIXABAY_TAGGED_DATA_DIR_PATH']);


    var batchName = 'pixabayDataFetchBatch';

    var logger = newBatchLogger(context);
    var pixabayUsername = process.env.PIXABAY_SECRET_USER_NAME,
        pixabayKey = process.env.PIXABAY_SECRET_KEY;
    var needsSecretFile = !(pixabayUsername && pixabayKey);
    if (needsSecretFile) {
        try {
            var secret = require(path.resolve(context.PIXABAY_SECRET_FILE_PATH));
            pixabayUsername = secret.username || pixabayUsername;
            pixabayKey = secret.key || pixabayKey;
        } catch (e) {
            var errMsg = 'context.PIXABAY_SECRET_FILE_PATH is wrong.';
            logger.fatal(errMsg);
            throw new Error(errMsg);
        }
    }
    var tagsFilename = path.resolve(context.PIXABAY_TAGS_FILE_PATH),
        dataDirname = path.resolve(context.PIXABAY_TAGGED_DATA_DIR_PATH);
    return {
        name: batchName,
        run: function (callback) {

            logger.batchStart(batchName);

            function abort(err) {
                logger.fatal(err.stack || err);
                logger.batchFail(batchName);
                callback(err);
            }

            function success() {
                logger.batchSuccess(batchName);
                callback(null);
            }

            mkdirP(dataDirname, function (err) {
                if (err) {
                    abort(err);
                    return;
                }
                exports._choiceTag(tagsFilename, function (err, tag) {
                    if (!tag) tag = 'flower';
                    if (err) {
                        abort(err);
                        return;
                    }
                    var query = {
                        username: pixabayUsername,
                        key: pixabayKey,
                        search_term: tag
                    };
                    logger.debug('Tag: %s', tag);
                    logger.trace('Query: %s', JSON.stringify(query, null, 4));
                    var fetchStartTime = new Date;
                    pixabayApiFetch(query, function (err, data) {
                        var tookTime = new Date() - fetchStartTime;
                        logger.trace('Fetch took time: %sms', tookTime);
                        if (err) {
                            abort(err);
                            return;
                        }
                        if (!data.totalHits) {
                            logger.error(JSON.stringify(data, null, 4));
                            abort(new Error('Failed to fetch pixabay data.'));
                            return;
                        }
                        logger.debug('Total hits: %s', data.totalHits);
                        logger.debug('Fetched : %s', data.hits && data.hits.length);

                        var tags = exports._correctTags(data);
                        exports._saveTags(tagsFilename, tags, function (err) {
                            if (err) {
                                abort(err);
                                return;
                            }
                            logger.debug('File crated: %s', tagsFilename);
                            var dataFilename = path.resolve(dataDirname,
                                ['pixabay', tag, 'data'].join('-') + '.json');
                            writeReadonlyFile(dataFilename, JSON.stringify(data, null, 4), function (err) {
                                if (err) {
                                    abort(err);
                                } else {
                                    logger.debug('File created: %s', dataFilename);
                                    success();
                                }
                            });
                        });
                    });
                });
            });
        }
    }
};
exports._choiceTag = function (tagsFilename, callback) {
    fs.exists(tagsFilename, function (exists) {
        if (!exists) {
            callback(null);
            return;
        }
        var tag = shuffled(require(tagsFilename) || []).shift() || '';
        callback(null, tag);
    });
};

exports._saveTags = function (tagsFilename, tag, callback) {
    fs.exists(tagsFilename, function (exists) {
        var data = (exists ? require(tagsFilename) : [])
            .concat(tag)
            .filter(newUniqueFilter())
            .filter(function (data) {
                return !!data;
            });
        writeReadonlyFile(tagsFilename, JSON.stringify(data, null, 4), function (err) {
            callback(err);
        });
    });
};

exports._correctTags = function (data) {
    return (data.hits || [])
        .map(function (data) {
            return data.tags.split(/[,\s]/g);
        }).reduce(function (a, b) {
            return [].concat(a).concat(b);
        }, [])
        .filter(newUniqueFilter());
};