import Rx from 'rxjs/Rx';

import {
  spawn,
} from 'spawn-rx';

const path = require('path');

// TODO: Check for sys.prefix/share/jupyter/kernels/*/kernel.json
/**
 * ipyKernelTryObservable check for existence of ipykernel in an env
 * @param  {Object} env  the current environment
 * @return {Observable}  an observable that emits the environment when the
 * source observable is also emitting something (source comes from the spawn())
 */
export function ipyKernelTryObservable(env) {
  const executable = path.join(env.prefix, 'bin', 'python');
  return spawn(executable, ['-m', 'ipykernel', '--version'], { split: true })
    .filter(x => x.source && x.source === 'stdout')
    .mapTo(env)
    .catch(err => Rx.Observable.empty());
}

/**
  * condaInfoObservable executes the conda indo --json command and maps the
  * result to an observable that parses through the environmental informaiton.
  * @return {Observable}  observable that emits the JSON parsed info
  */
export function condaInfoObservable() {
  return spawn('conda', ['info', '--json'])
    .map(info => JSON.parse(info));
}

/**
  * condaEnvsObservable that will return an observable that emits the environmental
  * paths of the passed in observable.
  * @param {Observable}   takes in an observable with environmental information.
  * @return {Observable}  an observable that contains a list of environmental
  * elements.
  */
export function condaEnvsObservable(condaInfo$) {
  return condaInfo$.map(info => {
    const envs = info.envs.map(env => ({ name: path.basename(env), prefix: env }));
    envs.push({ name: 'root', prefix: info.root_prefix });
    return envs;
  })
  .map(envs => envs.map(ipyKernelTryObservable))
  .mergeAll()
  .mergeAll()
  .toArray();
}

/**
  * createKernelSpecsFromEnvs generates a dictionary with the environmental paths.
  * @param {Observable}   takes in an observable with environmental elements
  * @return {Object}    returns a dictionary object containing the supported
  * language environments.
  */
export function createKernelSpecsFromEnvs(envs) {
  const displayPrefix = 'Python'; // Or R
  const languageKey = 'py'; // or r

  // TODO: Handle Windows & Conda
  const languageExe = 'bin/python';
  const jupyterBin = 'bin/jupyter';

  const langEnvs = {};

  for (const env of envs) {
    const base = env.prefix;
    const exePath = path.join(base, languageExe);
    const envName = env.name;
    const name = `conda-env-${envName}-${languageKey}`;
    langEnvs[name] = {
      display_name: `${displayPrefix} [conda env:${envName}]`,
      // TODO: Support default R kernel
      argv: [exePath, '-m', 'ipykernel', '-f', '{connection_file}'],
      language: 'python',
      // TODO: Provide resource_dir
    };
  }
  return langEnvs;
}

/**
  * condaKernelObservable generates an observable containing the supported language
  * environmental elements.
  * @return {Observable}  emits supported language elements
  */
export function condaKernelsObservable() {
  return condaEnvsObservable(condaInfoObservable())
    .map(createKernelSpecsFromEnvs);
}

@@ -190,21 +190,26 @@
 le check
+s
  for 
+the 
 existenc
@@ -230,14 +230,24 @@
  in 
-an
+the
  env
+ironment.
 %0A * 
@@ -268,21 +268,17 @@
 t%7D env  
-the c
+C
 urrent e
@@ -317,137 +317,26 @@
 e%7D  
-an observable that emits the environment when the%0A * source observable is also emitting something (source comes from the spawn())
+Source environment
 %0A */
@@ -683,17 +683,17 @@
 conda in
-d
+f
 o --json
@@ -823,34 +823,8 @@
 e%7D  
-observable that emits the 
 JSON
@@ -835,16 +835,23 @@
 sed info
+rmation
 %0A  */%0Aex
@@ -999,21 +999,16 @@
 ervable 
-that 
 will ret
@@ -1123,37 +1123,9 @@
 %7D   
-takes in an observable with e
+E
 nvir
@@ -1144,17 +1144,16 @@
 ormation
-.
 %0A  * @re
@@ -1175,39 +1175,9 @@
 e%7D  
-an observable that contains a l
+L
 ist 
@@ -1179,33 +1179,32 @@
 List of envi
-r
 onmental
 %0A  * element
@@ -1195,22 +1195,18 @@
 ntal
-%0A  * elements.
+ variables
 %0A  *
@@ -1616,29 +1616,38 @@
 ith the 
-environmental
+supported langauge%0A  *
  paths.%0A
@@ -1676,37 +1676,9 @@
 %7D   
-takes in an observable with e
+E
 nvir
@@ -1723,19 +1723,9 @@
     
-returns a d
+D
 icti
@@ -1734,15 +1734,8 @@
 ary 
-object 
 cont
@@ -1733,36 +1733,32 @@
 nary containing 
-the 
 supported%0A  * la
@@ -1754,33 +1754,23 @@
 rted
-%0A  *
  lang
-uage environment
+auges path
 s.%0A 
@@ -2603,16 +2603,17 @@
 language
+s
 %0A  * env
@@ -2663,15 +2663,9 @@
 e%7D  
-emits s
+S
 uppo

Correct kernels documentation and typos.