const { db } = require('../utils');

const modelAttributes = ['closeAt', 'id', 'list_exported', 'name', 'openAt', 'performDate'];

let cachedCurrentPerformance;

class Performance {

  constructor(id, name, openAt, closeAt, performDate) {
    this._id = id;
    this._name = name;
    this._openAt = new Date(openAt);
    this._closeAt = new Date(closeAt);
    this._performDate = new Date(performDate);
  }

  static get attributes() {
    return modelAttributes;
  }

  static get idName() {
    return 'id';
  }

  static get tableName() {
    return 'performances';
  }

  static create(name, performDate, openAt, closeAt) {
    const sql = 'INSERT INTO performances (name, performDate, openAt, closeAt) VALUES ($1, $2, $3, $4) RETURNING id, closeAt';

    if (
      Number.isNaN(Date.parse(openAt)) ||
      Number.isNaN(Date.parse(closeAt)) ||
      Number.isNaN(Date.parse(performDate))
    ) {
      return Promise.reject();
    } else {
      return db.query(
        sql,
        [name, performDate, openAt, closeAt],
        instanceFromRowPerformanceWithoutId(name, openAt, closeAt, performDate)
      );
    }
  }

  static findAll() {
    const sql = 'SELECT * FROM performances';

    return db.query(sql, [], instanceFromRowPerformance);
  }

  static findCurrent() {
    if (cachedCurrentPerformance && Date.now() < cachedCurrentPerformance.closeAt) {
      return Promise.resolve(cachedCurrentPerformance);
    }
    const sql = 'SELECT * FROM performances WHERE now() < closeAt ORDER BY openAt ASC LIMIT 1';

    return db.query(sql, [], instanceFromRowPerformance)
    .then((currentPerformance) => {
      cachedCurrentPerformance = currentPerformance;
      return currentPerformance;
    });
  }

  static findForListExporting() {
    const sql = 'SELECT * from performances WHERE not list_exported AND closeat < now() ORDER BY id asc';

    return db.query(sql, [], instanceFromRowPerformance);
  }

  static update(attributes) {
    const id = attributes.id;

    if (typeof id === 'undefined') {
      return Promise.reject(new Error('No id provided with attributes'));
    }

    delete attributes.id;
    const { sql, values } = db.queryBuilder(Performance, attributes, { statement: 'UPDATE', id });

    return db.query(sql, values);
  }

  get closeAt() {
    return this._closeAt;
  }

  get id() {
    return this._id;
  }

  get name() {
    return this._name;
  }

  get openAt() {
    return this._openAt;
  }

  inPerformanceWindow() {
    return this._openAt < Date.now() && Date.now() < this._closeAt;
  }

  toJSON() {
    return {
      closeAt: this._closeAt.toISOString(),
      id: this._id,
      name: this._name,
      openAt: this._openAt.toISOString(),
      performDate: this._performDate.toISOString(),
      windowOpen: this.inPerformanceWindow()
    };
  }

}

const instanceFromRowPerformance = ({ id, name, openat, closeat, performdate }) =>
  new Performance(id, name, openat, closeat, performdate);

const instanceFromRowPerformanceWithoutId = (name, openAt, closeAt, performDate) =>
  ({ id }) => new Performance(id, name, openAt, closeAt, performDate);

module.exports = Performance;

@@ -189,24 +189,38 @@
 structor(id,
+ listExported,
  name, openA
@@ -261,24 +261,63 @@
 s._id = id;%0A
+    this._listExported = listExported;%0A
     this._na
@@ -2399,24 +2399,83 @@
 s._id;%0A  %7D%0A%0A
+  get listExported() %7B%0A    return this._listExported;%0A  %7D%0A%0A
   get name()
@@ -2469,32 +2469,32 @@
 %0A  get name() %7B%0A
-
     return this.
@@ -2552,16 +2552,73 @@
 t;%0A  %7D%0A%0A
+  get performDate() %7B%0A    return this._performDate;%0A  %7D%0A%0A
   inPerf
@@ -3017,16 +3017,31 @@
 = (%7B id,
+ list_exported,
  name, o
@@ -3087,32 +3087,47 @@
  Performance(id,
+ list_exported,
  name, openat, c
@@ -3233,16 +3233,16 @@
 ate) =%3E%0A
-
   (%7B id 
@@ -3266,16 +3266,23 @@
 ance(id,
+ false,
  name, o

update Performance with new attribute