import Ajv from 'ajv';
import ItemView from './itemView';
import { getSession } from '../auth';
import { apiUrl } from '../config.json';

const m = require('mithril');

// Mapper for resource vs schema-object names
const objectNameForResource = {
  users: 'User',
  groupmembershipds: 'Groupmembership',
  groups: 'Group',
  eventsignups: 'Eventsignup',
  events: 'Event',
};

export default class EditView extends ItemView {
  /* Extension of ItemView to edit a data item
   *
   * Requires:
   * - call constructor with vnode, resource, (valid, true by default)
   * - vnode.attrs.onfinish has to be a callback function that is called after
   *   the edit is finished
   *
   * Provides Methods:
   * - bind(attrs): binds a form-field against this.data
   * - submit
   */
  constructor(vnode, resource, embedded, valid = true) {
    super(resource, embedded);
    this.changed = false;
    this.resource = resource;

    // state for validation
    this.valid = valid;
    this.ajv = new Ajv({
      missingRefs: 'ignore',
      errorDataPath: 'property',
      allErrors: true,
    });
    this.errors = {};
    this.data = {};

    // callback when edit is finished
    this.callback = vnode.attrs.onfinish;
  }

  oninit() {
    if (this.id) {
      // load data for item
      this.handler.getItem(this.id, this.embedded).then((item) => {
        this.data = item;
        m.redraw();
      });
    }
    // load schema
    m.request(`${apiUrl}docs/api-docs`).then((schema) => {
      const objectSchema = schema.definitions[
        objectNameForResource[this.resource]];
      console.log(schema);
      //this.ajv.addSchema(objectSchema, 'schema');
    });
  }

  // bind form-fields to the object data and validation
  bind(attrs) {
    // initialize error-list for every bound field
    if (!this.errors[attrs.name]) this.errors[attrs.name] = [];

    const boundFormelement = {
      onChange: (name, value) => {
        this.changed = true;
        // bind changed data
        this.data[name] = value;

        //console.log(this.data);

        // validate against schema
        /*const validate = this.ajv.getSchema('schema');
        this.valid = validate(this.data);
        console.log(validate.schema);

        console.log(validate.errors);
        if (this.valid) {
          Object.keys(this.errors).forEach((field) => {
            this.errors[field] = [];
          });
        } else {
          // get errors for respective fields
          Object.keys(this.errors).forEach((field) => {
            const errors = validate.errors.filter(error =>
              `.${field}` === error.dataPath);
            this.errors[field] = errors.map(error => error.message);
          });
        }*/
      },
      getErrors: () => this.errors[attrs.name],
      value: this.data[attrs.name],
    };
    // add the given attributes
    Object.keys(attrs).forEach((key) => { boundFormelement[key] = attrs[key]; });

    return boundFormelement;
  }

  submit(method) {
    return () => {
      if (this.changed) {
        let request;
        if (method === 'POST') {
          request = this.handler.post(this.data);
        } else if (method === 'PATCH') {
          request = this.handler.patch(this.data);
        }
        request.then((response) => {
          this.callback(response);
        }).catch((error) => {
          console.log(error);
          // Process the API error
          const { response } = error;
          if (response.status === 422) {
            // there are problems with some fields, display them
            Object.keys(response.data._issues).forEach((field) => {
              this.errors[field] = [response.data._issues[field]];
            });
            m.redraw();
          } else if (response.status === 403) {
            // Unauthorized
            m.route.set('/login');
          } else {
            console.log(error);
          }
        });
      } else {
        this.callback();
      }
    };
  }
}