// Generated by CoffeeScript 1.10.0
(function() {
  var Model, NoSchema, WrongSchemaError, _default, _isArray, _isMap, _toString, castObject, castValue, log, ref, reportCastIgnore,
    hasProp = {}.hasOwnProperty,
    indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  log = require('printit')({
    prefix: 'Cozy DB'
  });

  WrongSchemaError = require('./errors').WrongSchemaError;

  _toString = function(x) {
    return Object.prototype.toString.call(x);
  };

  _isArray = Array.isArray || function(x) {
    return '[object Array]' === _toString(x);
  };

  _isMap = function(x) {
    return '[object Object]' === _toString(x);
  };

  _default = function(value, defaultValue, lastDefault) {
    if (value !== void 0) {
      return value;
    } else if (defaultValue !== void 0) {
      return defaultValue;
    } else {
      return lastDefault;
    }
  };

  reportCastIgnore = ((ref = process.env.NODE_ENV) !== 'production' && ref !== 'test') || process.env.NO_CAST_WARNING;

  exports.NoSchema = NoSchema = {
    symbol: 'NoSchema'
  };

  exports.castValue = castValue = function(value, typeOrOptions) {
    var arrayType, defaultValue, i, item, key, len, out, pvalue, result, type;
    if (typeOrOptions.type) {
      type = typeOrOptions.type;
      defaultValue = typeOrOptions['default'];
    } else {
      type = typeOrOptions;
      defaultValue = void 0;
    }
    if (value === void 0 || value === null) {
      if (_isArray(type)) {
        return [];
      } else {
        return defaultValue;
      }
    }
    if (type === NoSchema) {
      out = value;
    } else if (type === Date) {
      value = _default(value, defaultValue, void 0);
      out = new Date(value);
    } else if (type === String) {
      value = _default(value, defaultValue, void 0);
      out = String(value);
    } else if (type === Boolean) {
      value = _default(value, defaultValue, void 0);
      out = Boolean(value);
    } else if (type === Number) {
      value = _default(value, defaultValue, void 0);
      out = Number(value);
    } else if (type === Object) {
      out = {};
      for (key in value) {
        if (!hasProp.call(value, key)) continue;
        pvalue = value[key];
        out[key] = pvalue;
      }
    } else if (type.prototype instanceof Model) {
      out = type.cast(value);
    } else if (_isArray(type)) {
      if (!type[0]) {
        throw WrongShemaError('empty array');
      }
      value = _default(value, defaultValue, []);
      arrayType = type[0];
      result = [];
      if ((value != null) && typeof value !== 'string') {
        for (i = 0, len = value.length; i < len; i++) {
          item = value[i];
          result.push(castValue(item, arrayType));
        }
      }
      return result;
    } else if (typeof type === 'function') {
      return type(value);
    } else {
      throw WrongShemaError("unsuported type ", type);
    }
    return out;
  };

  exports.castObject = castObject = function(raw, schema, target, name) {
    var handled, prop, typeOrOptions, value;
    if (target == null) {
      target = {};
    }
    handled = [];
    if (schema === NoSchema) {
      for (prop in raw) {
        value = raw[prop];
        target[prop] = value;
      }
      return target;
    }
    for (prop in schema) {
      if (!hasProp.call(schema, prop)) continue;
      typeOrOptions = schema[prop];
      target[prop] = castValue(raw[prop], typeOrOptions);
      if (reportCastIgnore) {
        handled.push(prop);
      }
    }
    if (reportCastIgnore) {
      for (prop in raw) {
        if (!hasProp.call(raw, prop)) continue;
        value = raw[prop];
        if (indexOf.call(handled, prop) < 0) {
          log.warn("Warning : cast ignored property '" + prop + "' on '" + name + "'");
        }
      }
    }
    return target;
  };

  Model = require('../model');

}).call(this);
