import _User from './_User.js';
import isArray from './util/isArray.js';
import isUndefined from './util/isUndefined.js';

var _DB = {};

_DB.records = {};

_DB.insertRecord = function(record, type, structure){
  if(!isUndefined(type)){  record.type = type;  }
  var record_copy = _DB.copyAndTransform(record, structure);  // make a copy in case the record has references to other objects, possibly circular
  // TODO: Figure-out what to do for image, which has long `src_base64` property, so it must be stored in a file, with a mere reference in the DB. Also, upon creation the automatically makes thumbnails and updates the record accordingly, which is not possible to trigger.
  return m.request({
      method: 'POST',
      url: '/cgi/insertrecord',
      body: {
        session_hash: _User.session_hash,
        record: record_copy
        }
      })
    .then(function(res){
      if(res.success === true){
        record.id = res.id;
        _DB.integrate(record);
        }
      });
  };

_DB.getRecord = function(id){
  return _DB.records[id];
  };

_DB.removeRecord = function(record){
  delete _DB.records[record.id];
  // TODO: make a call to server too? This is called by _Item.deleteImage, which itself calls the server anyway because deleting an image has special logic
  }

_DB.integrate = function(new_record){
  // check if record "exists" by id:
  if(_DB.records.hasOwnProperty(new_record.id)){
    // if it does exist, update its properties
    var old_record = _DB.records[new_record.id];
    Object.keys(new_record).forEach(function(key){
      old_record[key] = new_record[key];
      });
    }
  else{
    // if it doesn't exist, make it
    _DB.records[new_record.id] = new_record;
    }
  return _DB.records[new_record.id]; // in case we want the latest version of the record; see _OpenOrders for an example
  };

_DB.integrateAll = function(new_records){
  new_records.forEach(function(new_record, i){  // TODO: ensure this is best behavior e.g. cart.lineitems; we want the latest lineitem list, with the proper things removed and added, not only added and none removed
    new_records[i] = _DB.integrate(new_record);
    });
  return new_records;
  };
_DB.integrateAllReturnIds = function(new_records){
  new_records.forEach(function(new_record, i){  // TODO: ensure this is best behavior e.g. cart.lineitems; we want the latest lineitem list, with the proper things removed and added, not only added and none removed
    new_records[i] = _DB.integrate(new_record).id;
    });
  return new_records;
  };


// determines whether to replace the whole array, or append to the existsing array, etc.
_DB.integrateArray = function(record_id, property, new_array){
  
  }

/*
 schema = {
  id: 'copy',
  brand: 'copy',
  item: 'replace-with-id',  // only get the id of the record, don't copy it
  item2: {
    id: 'copy',   // automatically makes separate top-level record for item2, and sets `record.item2 = item2`
    brand: 'copy'
    },
  lineitems: [
    'list',  // shows that this is a list
    {                     // this is the substructure of each element in the list
      id: 'copy',         // if substructure is left-out, then it's a list of scalars
      quantity: 'copy'    // if substructure == 'replace-with-id', it's a list of records, but only ids are transferred
      }
    ]
  }
 */
_DB.getOne = function(id, type, structure){
  return m.request({
    method: 'POST',
    url: '/cgi/getone',
    body: {
      session_hash: _User.session_hash,
      id: id,
      type: type,
      structure: structure
      }
    })
  .then(function(res){
    if(res.success === true){
      _DB.integrate(res.record);
      }
    });
  }

/* // exclude: big security problem, since record permissions aren't individualized; an attacker could just send an empty `structure` and get the whole DB
_DB.getAll = function(filter, structure){
  return m.request({
    method: 'POST',
    url: '/cgi/getall',
    body: {
      session_hash: _User.session_hash,
      filter: filter,
      structure: structure
      }
    })
  .then(function(res){
    if(res.success === true){
      if(!isArray(res.records)){ res.records = []; }  // the JSON encoder sends an empty array as an object instead of array
      res.records.forEach(_DB.integrate);
      }
    });
  }
  */

_DB.setProperty = function(record, key, value){
  var old_value = record[key];
  record[key] = value;
  return m.request({
    method: 'POST',
    url: '/cgi/setproperty',
    body: {
      session_hash: _User.session_hash,
      record_id: record.id,
      record_type: record.type,
      key: key,
      value: value
      }
    })
  .then(function(res){
    if(res.success === true){
      return value;
      }
    else{
      record[key] = old_value;
      _Message.addError('There was an error updating '+record.type+' #'+record.id+'.');
      return old_value;
      }
    });
  };

_DB.copyAndTransform = function(record, structure){
  var record_copy = {};
  Object.keys(structure).forEach(function(key){
    var operation = structure[key];
    if(operation === 'copy'){
      record_copy[key] = record[key];
      }
    else if(operation === 'replace-with-id'){
      record_copy[key] = record[key].id;
      }
    });
  return record_copy;
  };

export default _DB;