/**
 * Define an object with strict initializer.
 * The defined object requires to pass object for it's accessors on initialize.
 * If unknown key passed, initializer throws an error.
 * @function lib.object.defineStrict
 * @param {object} def - Object definition.
 * @returns {object} - Defined object.
 * @author Taka Okunishi
 *
 */
var define = require('./define'),
    format = require('util').format;

function newUnknownKeyError(key, value) {
    return new Error(format('Unknown key: "%s"', key));
}

module.exports = function (def) {
    var _init = def.init;
    def.init = function (data) {
        var s = this;
        if (!data) data = {};
        Object.keys(data).forEach(function (key) {
            var value = data[key];
            if (key.match(/^__/)) {
                s[key] = value;
                return;
            }
            if (key.match(/^_/)) key = key.replace(/^_/, '');
            var accessor = s[key];
            if (!accessor) {
                throw newUnknownKeyError(key, value);
            }
            accessor.call(s, value);
        });
        if (_init) _init.call(s, arguments);
    };
    return define(def);
};