'use strict';

import Joi from 'joi';
import SchemaValidator from 'validate';
import GraphError  from './../exception';
import _ from 'lodash';

const ORIENTDB_TYPES_MAP = {
  'decimal': 'number',
  'float': 'number',
  'integer': 'number',
  'double': 'number',
  'short': 'number',
  'date': 'object',
  'datetime': 'object',
  'string': 'string',
  'boolean': 'boolean',
};

const VertexClassSchema = Joi.object().pattern(/^[$A-Z_][0-9A-Z_$]*$/i, Joi.object().keys({
  type: Joi.string().required(),
  index: Joi.string().default(null),
  match: Joi.string().default(null),
  message: Joi.string().default('There is an error')
}));


class Schema {
  constructor(structure) {
    this.structure = structure;

    // Validate the structure of model
    let validator = VertexClassSchema.validate(structure);
    if (validator.error) {
      throw new GraphError('VERTEX_SCHEMA_ERROR', 'Invalid vertex schema', {errors: validator.error});
    }
    // Create validator removing keys not allowed.
    // Index is the only not allowed key
    this.validator = SchemaValidator(_.mapValues(_.cloneDeep(this.structure), (field) => {
      delete field['index'];
      let fieldType = ORIENTDB_TYPES_MAP[field['type']];
      
      if (fieldType == undefined){
        throw new GraphError('VERTEX_SCHEMA_ERROR', 'Invalid field type', {errors: [`Type ${field['type']} is not supported by rieluz`]});
      }
      
      field['type'] = fieldType; 
      return field;
    }));

    this.errors = null;
  }

  validate(obj) {
    let errors = this.validator.validate(obj);

    this.errors = _.map(errors, (item) => {
      item['field'] = item.path;
      delete item['path'];
      return item;
    });

    return _.isEmpty(this.errors);
  }
}

export default Schema;


@@ -148,183 +148,516 @@
 nst 
-ORIENTDB_TYPES_MAP = %7B%0A  'decimal': 'number',%0A  'float': 'number',%0A  'integer': 'number',%0A  'double': 'number',%0A  'short': 'number',%0A  'date': 'object',%0A  'datetime': 'object'
+toDate = (value) =%3E new Date(value);%0A%0Aconst ORIENTDB_TYPES_MAP = %7B%0A  'decimal': %7B%0A    type: 'number',%0A    formatter: parseFloat%0A  %7D,%0A  'float': %7B%0A    type: 'number',%0A    formatter: parseFloat%0A  %7D,%0A  'integer': %7B%0A    type: 'number',%0A    formatter: parseInt%0A  %7D,%0A  'double': %7B%0A    type: 'number',%0A    formatter: parseFloat%0A  %7D,%0A  'short': %7B%0A    type: 'number',%0A    formatter: parseInt%0A  %7D,%0A  'date': %7B%0A    type: 'object',%0A    formatter: toDate%0A  %7D,%0A  'datetime': %7B%0A    type: 'object',%0A    formatter: toDate%0A  %7D
 ,%0A  
@@ -1772,10 +1772,56 @@
 Type
+.type != undefined ? fieldType.type : fieldType
 ;
- 
 %0A   
@@ -1890,24 +1890,400 @@
 date(obj) %7B%0A
+%0A    const keys = Object.keys(obj);%0A    for (let key in keys) %7B%0A      const value = keys%5Bkey%5D;%0A      const field = this.structure%5Bvalue%5D;%0A%0A      const fieldType = ORIENTDB_TYPES_MAP%5Bfield.type%5D;%0A%0A      if (obj.hasOwnProperty(value) && fieldType.formatter != undefined) %7B%0A        const formatter = fieldType.formatter;%0A        obj%5Bvalue%5D = formatter(obj%5Bvalue%5D)%0A      %7D%0A    %7D%0A%0A
     let erro

Format value to specified data type