'use strict';

const Promise = require('bluebird');
const _ = require('lodash');
const Controller = require('./controller');

class RestfulController extends Controller {

    constructor(manager, model) {
        super(manager);

        this._model = model || null;
    }

    model(request) {
        if(!this._model) {
            throw new Error('model not defined');
        }

        return this._model
            .then(model => {
                return this
                    .emit('model', [model, request])
                    .then(resp => {
                        if(typeof resp !== 'undefined') {
                            return resp;
                        }

                        return model;
                    })
            });
    }

    getModelPrimaryKey(model) {
        let idField = null;

        for(let key in model.attributes) {
            // if(key == 'id') {
            //     idField = key;
            // }

            if('primaryKey' in model.attributes[key] && model.attributes[key].primaryKey) {
                return key;
            }
        }

        return idField;
    }

    /* -------------------------------------------------------------------------
     * Methods
     * ---------------------------------------------------------------------- */

    list(request) {
        return this
            .emit('list', [request])
            .then(resp => {
                if(typeof resp != 'undefined') {
                    return resp;
                }

                let opts = request.query;

                return this
                    .model(request)
                    .then(Model => {
                        return Model
                            .findAll(opts);
                    });
            })
    }

    fetch(request) {
        return this
            .emit('fetch', [request])
            .then(resp => {
                if(typeof resp != 'undefined') {
                    return resp;
                }

                if(!request.params.id) {
                    throw new Error('id required');
                }

                let id = request.params.id;

                return this
                    .model(request)
                    .then(Model => {
                        return Model
                            .findById(id);
                    })
                    .then(instance => {
                        if(!instance) {
                            let err = new Error('record not found');
                            err.code = 404;
                            err.status = 404;

                            return Promise.reject(err);
                        }

                        return instance;
                    });
            });
    }

    count(options) {
        return Promise.resolve(this.options.limit);
    }

    create(request) {
        return this
            .emit('create', [request])
            .then(resp => {
                if(typeof resp != 'undefined') {
                    return resp;
                }

                return this
                    .model(request)
                    .then(Model => {
                        let data = request.body;
                        return Model.create(data);
                    });
            });
    }

    update(request) {
        return this
            .emit('update', [request])
            .then(resp => {
                if(typeof resp != 'undefined') {
                    return resp;
                }

                return this
                    .model(request)
                    .then(Model => {
                        let idField = this.getModelPrimaryKey(Model);

                        if(!idField) {
                            throw new Error('primary key field not defined');
                        }

                        let where = {};
                        where[idField] = request.params.id;

                        let data = request.body;

                        return Model
                            .findOne({
                                where: where,
                            })
                            .catch(err => {
                                if(err.code != 404) {
                                    return Promise.reject(err.code);
                                }

                                data[idField] = request.params.id;
                                return Model.build(data);
                            })
                            .then(instance => {
                                if(!instance) {
                                    data[idField] = request.params.id;
                                    return Model.create(data);
                                }

                                return instance.update(data);
                            })
                    });
            });
    }

    destroy(request) {
        return this
            .emit('destroy', [request])
            .then(resp => {
                if(typeof resp != 'undefined') {
                    return resp;
                }

                if(!request.params.id) {
                    throw new Error('where required');
                }

                return this
                    .model(request)
                    .then(Model => {
                        let idField = this.getModelPrimaryKey(Model);

                        if(!idField) {
                            throw new Error('primary key field not defined');
                        }

                        let where = {};
                        where[idField] = request.params.id;

                        return Model
                            .destroy({
                                where: where
                            });
                    });
            });
    }
}

module.exports = RestfulController;