'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.newNotebookEpic = exports.loadEpic = exports.convertRawNotebook = exports.extractNewKernel = exports.notebookLoaded = exports.newNotebook = exports.load = exports.NEW_NOTEBOOK = exports.SET_NOTEBOOK = exports.LOAD = undefined;

var _commutable = require('commutable');

var _actions = require('../actions');

const Rx = require('rxjs/Rx');
const fs = require('fs');
const commutable = require('commutable');

const path = require('path');

const Observable = Rx.Observable;

const readFileObservable = (filename, ...args) => Observable.create(observer => {
  fs.readFile(filename, ...args, (error, data) => {
    if (error) {
      observer.error(error);
    } else {
      observer.next({ filename, data });
      observer.complete();
    }
  });
});

const LOAD = exports.LOAD = 'LOAD';
const SET_NOTEBOOK = exports.SET_NOTEBOOK = 'SET_NOTEBOOK';
const NEW_NOTEBOOK = exports.NEW_NOTEBOOK = 'NEW_NOTEBOOK';

const load = exports.load = filename => ({ type: LOAD, filename });

const newNotebook = exports.newNotebook = (kernelSpecName, cwd) => ({
  type: NEW_NOTEBOOK,
  kernelSpecName,
  cwd: cwd || process.cwd()
});

// Expects notebook to be JS Object or Immutable.js
const notebookLoaded = exports.notebookLoaded = (filename, notebook) => ({
  type: SET_NOTEBOOK,
  filename,
  notebook
});

const extractNewKernel = exports.extractNewKernel = (filename, notebook) => {
  const cwd = filename && path.dirname(path.resolve(filename)) || process.cwd();
  const kernelName = notebook.getIn(['metadata', 'kernelspec', 'name'], notebook.getIn(['metadata', 'language_info', 'name'], 'python3')); // TODO: keep default kernel consistent
  return (0, _actions.newKernel)(kernelName, cwd);
};

const convertRawNotebook = exports.convertRawNotebook = ({ filename, data }) => ({
  filename,
  notebook: commutable.fromJS(JSON.parse(data))
});

// TODO: ERROR_LOADING response

const loadEpic = exports.loadEpic = actions => actions.ofType(LOAD).do(action => {
  // If there isn't a filename, save-as it instead
  if (!action.filename) {
    throw new Error('load needs a filename');
  }
})
// Switch map since we want the last load request to be the lead
.switchMap(action => readFileObservable(action.filename).map(convertRawNotebook).flatMap(({ filename, notebook }) => Observable.of(notebookLoaded(filename, notebook), extractNewKernel(filename, notebook))).catch(err => Observable.of({ type: 'ERROR', payload: err, error: true })));

const starterNotebook = (0, _commutable.appendCell)(_commutable.emptyNotebook, _commutable.emptyCodeCell);
const newNotebookEpic = exports.newNotebookEpic = action$ => action$.ofType(NEW_NOTEBOOK).switchMap(action => Observable.of({
  type: 'SET_NOTEBOOK',
  notebook: starterNotebook
}, (0, _actions.newKernel)(action.kernelSpecName)));