/**
 * job.js
 * Copyright (c) 2016 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 sqlBuilder = require('sql');
var _ = require('underscore');

var dibs = require('../../core/dibs.js');
var tables = require('./tables.js');
var utils = require('../../lib/utils.js');

sqlBuilder.setDialect('mysql');

module.exports.selectJob = selectJob;
module.exports.selectJobCount = selectJobCount;
module.exports.selectJobInfo = selectJobInfo;
module.exports.selectJobBoard = selectJobBoard;

var jobs = tables.jobs();
var users = tables.users();

function assembleWhereClause(clauseObject, condition) {
    if (clauseObject.count === 0) {
        clauseObject.clause = condition;
    } else {
        clauseObject.clause = clauseObject.clause.and(condition);
    }

    clauseObject.count++;

    return clauseObject;
}


function generateWhereClause(options) {
    var whereClause = {
        clause: {},
        count: 0
    };

    if (options.id) {
        var id = options.id;

        var arraySyntax = new RegExp('^\\[.*\\]$');
        if (arraySyntax.test(id)) {
            var arrayString = id.substr(1, id.length - 2);
            id = options.id = arrayString.split(',');
            options.parent_id = undefined;
        }

        if (_.isArray(id)) {
            whereClause =
                assembleWhereClause(whereClause, jobs.id.in(id));
        } else {
            whereClause =
                assembleWhereClause(whereClause, jobs.id.equals(id));
        }
    }

    // TODO
    // need to change variable name. it is confusing!!
    // too many variables for parent id
    if (!options.parentId && options.parent) {
        options.parent_id = options.parentId = options.parent;
    }

    if (options.parent_id) {
        if (options.parent_id === 'NULL') {
            whereClause =
                assembleWhereClause(whereClause, jobs.parent_id.isNull());
        } else {
            whereClause =
                assembleWhereClause(whereClause, jobs.parent_id.equals(options.parent_id));
        }
    }

    if (options.distribution_name) {
        whereClause =
            assembleWhereClause(whereClause, jobs.distribution_name.equals(options.distribution_name));
    }

    if (options.project_name) {
        whereClause =
            assembleWhereClause(whereClause, jobs.project_name.like('%' + options.project_name + '%'));
    }

    if (options.project_type) {
        whereClause =
            assembleWhereClause(whereClause, jobs.project_type.equals(options.project_type));
    }

    if (options.environment_name) {
        whereClause =
            assembleWhereClause(whereClause, jobs.environment_name.equals(options.environment_name));
    }

    if (options.status) {
        whereClause =
            assembleWhereClause(whereClause, jobs.status.equals(options.status));
    }

    if (options.user_email) {
        whereClause =
            assembleWhereClause(whereClause, jobs.user_email.equals(options.user_email));
    }

    if (options.user_name) {
        whereClause =
            assembleWhereClause(whereClause, users.name.equals(options.user_name));
    }

    if (options.start_time) {
        whereClause =
            assembleWhereClause(whereClause, jobs.start_time.equals(options.start_time));
    }
    if (options.end_time) {
        whereClause =
            assembleWhereClause(whereClause, jobs.end_time.equals(options.end_time));
    }

    if (options.snapshot_name) {
        whereClause =
            assembleWhereClause(whereClause, jobs.snapshot_name.equals(options.snapshot_name));
    }

    if (options.start_snapshot_name) {
    }
    if (options.end_snapshot_name) {
    }

    return whereClause;
}


function selectJobInfo(conn, jobId, callback) {
    var jobInfo = sqlBuilder.define({
        name: 'job_info',
        columns: [
            'id', 'job_id', 'property', 'value', 'type'
        ]
    });

    var options = {};

    var statement = jobInfo.select(jobInfo.property, jobInfo.value, jobInfo.type)
        .from(jobInfo).where(jobInfo.job_id.equals(jobId)).toQuery();

    conn.query(statement.text, statement.values, function (err, results) {
        if (err) {
            dibs.log.error(err);
        } else {
            _.each(results, function (info) {
                options[info.property] = utils.stringAndTypeToObj(info.value, info.type);
            });
        }

        callback(err, options);
    });
}


function selectJobBoard(conn, jobId, callback) {
    var jobBoard = sqlBuilder.define({
        name: 'job_board',
        columns: [
            'id', 'job_id', 'time', 'type', 'name'
        ]
    });

    var board = {};
    var statement = jobBoard.select(jobBoard.id, jobBoard.time, jobBoard.type, jobBoard.name)
        .from(jobBoard).where(jobBoard.job_id.equals(jobId)).toQuery();

    conn.query(statement.text, statement.values, function (err, results) {
        if (err) {
            dibs.log.error(err);
            board = [];
        } else {
            board = results;
        }

        callback(err, board);
    });
}


function selectJobCount(conn, options, callback) {
    var totalCount = 0;
    var statement = jobs.select(jobs.count()).from(jobs.join(users)
        .on(jobs.user_email.equals(users.email)));

    var whereClause = generateWhereClause(options);

    if (whereClause.count > 0) {
        statement = statement.where(whereClause.clause);
    }
    statement = statement.toQuery();

    conn.query(statement.text, statement.values, function (err, count) {
        if (err) {
            dibs.log.error(err);
        } else {
            totalCount = count[0].jobs_count;
        }

        callback(err, totalCount);
    });
}


function selectJob(conn, options, callback) {

    var order = options.order;
    var limit = options.limit;
    var offset = options.offset;
    var count = options.count;

    var whereClause = generateWhereClause(options);

    var query = jobs.select(jobs.star(), users.name).from(jobs.join(users)
        .on(jobs.user_email.equals(users.email)));

    if (whereClause.count > 0) {
        query = query.where(whereClause.clause);
    }

    if (order === 'ASC') {
        query = query.order(jobs.id.asc);
    } else {
        query = query.order(jobs.id.desc);
    }

    if (limit) {
        query = query.limit(count).offset(offset);
    }

    query = query.toQuery();

    conn.query(query.text, query.values, function (err, results) {
        if (err) {
            dibs.log.error(err);
        }

        callback(err, results);
    });
}
