import Map from 'shared/model/map';
import { sortBy, last, get } from 'lodash';
import { action } from 'mobx';
import Exercise from './exercises/exercise';

const NEW = 'new';

export class ExerciseVersions extends Map {

  get(version) {
    if (version === 'latest') {
      return last(sortBy(this.array, 'version'));
    } else {
      return super.get(version);
    }
  }

}

export class ExercisesMap extends Map {

  createNewRecord() {
    const ex = Exercise.build({ id: NEW });
    this.set(NEW, ex);
    return ex;
  }

  findOrCreateNewRecord() {
    return this.get(NEW) || this.createNewRecord();
  }

  get(idWithVersion) {
    const [id, version = 'latest'] = String(idWithVersion).split('@');
    if (id === NEW) { return super.get(id) || this.createNewRecord(); }
    const versions = super.get(id);
    return versions ? versions.get(version) : null;
  }

  fetch(id) {
    if (!String(id).match(/@/)){ id = `${id}@latest`; }
    return { id };
  }

  @action onLoaded({ data, exercise }) {
    let versions = super.get(data.number);
    if (!versions) {
      versions = new ExerciseVersions();
      this.set(data.number, versions);
    }
    let existing = versions.get(data.version);
    if (exercise) {
      versions.set(data.version, exercise);
      exercise.published_at = data.published_at;
      existing = exercise;
    }
    existing ? existing.update(data) : versions.set(data.version, exercise || new Exercise(data));
  }

  @action ensureLoaded(numberWithVersion) {
    if (numberWithVersion === NEW) {
      this.findOrCreateNewRecord();
    } else if (!this.get(numberWithVersion)) {
      this.fetch(numberWithVersion);
    }
  }

  publish(exercise) {
    return { uid: exercise.uid, data: exercise.serialize() };
  }

  saveDraft(exercise) {
    const req = { data: exercise.serialize() };
    if (exercise.isNew) {
      Object.assign(req, { url: 'exercises', method: 'POST' });
    }
    return req;
  }

  onSaved({ data }, [exercise]) {
    exercise.error = null;
    this.onLoaded({ data, exercise });
  }

  onError(error, [exercise]) {
    exercise.error = get(error, 'response.data.errors[0].message', error);
  }

}


const exercisesMap = new ExercisesMap();

export { Exercise };
export default exercisesMap;

@@ -2089,24 +2089,24 @@
 xercise.
-e
+onE
 rror
- = 
+(
 get(erro
@@ -2148,18 +2148,26 @@
 ', error
+.message)
 )
-;
 %0A  %7D%0A%0A%7D%0A

use status as a fallback