import path from 'path';
import fs from 'fs';

import dir from 'node-dir';
import watch from 'watch';
import commandLineArgs from 'command-line-args';
import uuid from 'node-uuid';
import {BinaryClient} from 'binaryjs';

const cli = commandLineArgs([
    {
        name: 'dir',
        alias: 'd',
        type: String
    }
]);
const options = cli.parse();

const filesById = {};
let sendFileData;

function createStreamToServer(stream) {
    return function(hostedFileData) {
        stream.write(hostedFileData);
    };
}
const client = BinaryClient('ws://localhost:9000');

client.on('open', function() {
    console.log('opened connection');
    const stream = client.createStream();
    sendFileData = createStreamToServer(stream);
});
client.on('close', function() {
    console.log('connection closed');
});
client.on('error', function(err) {
    console.log('error: ', err);
});

function createTrackData(songFile) {
    const [number, song] = songFile.split('-');
    const [title, ] = song.split('.');
    const id = uuid.v1();
    return {
        number, title, id
    };
}

function extractTrack(file) {
    const [artist, album, songFile] = path.relative(options.dir, file).split(path.sep);
    const {number, title, id} = createTrackData(songFile);
    return {
        artist,
        album,
        file,
        number,
        title,
        id
    };
}

function buildFileInfoForBackend(map, track) {
    map[track.artist] = map[track.artist] || {};
    map[track.artist][track.album] = map[track.artist][track.album] || {};
    map[track.artist][track.album][track.number] = {id: track.id, title: track.title};
    return map;
}

function reduceAndMemoize(memo, memoKey, memoValue) {
    return function(array, reduceFunction, initial) {
        return array.reduce(function(previous, current) {
            memo[current[memoKey]] = current[memoValue];
            return reduceFunction(previous, current);
        });
    };
}

const processFile = reduceAndMemoize(filesById, 'id', 'file');

dir.files(options.dir, (err, files) => {
    if (err) {
        console.log(err);
        return;
    }

    if (files) {
        const hostedFiles = processFiles(files, buildFileInfoForBackend, {});
        sendFileData(hostedFiles);
    }
});

watch.createMonitor(options.dir, (monitor) => {
    monitor.on('created', (file) => {
        fs.lstat(file, (err, stat) => {
            if (stat.isFile()) {
                const hostedFiles = processFiles(files, buildFileInfoForBackend, {});
                sendFileData(hostedFiles);
            }
        });
    });

    monitor.on('removed', (file) => {
        console.log('removing file:', file);
    });
});

@@ -1923,32 +1923,41 @@
 rent);%0A        %7D
+, initial
 );%0A    %7D;%0A%7D%0A%0Acon
@@ -1966,20 +1966,22 @@
  process
-File
+Tracks
  = reduc
@@ -2137,24 +2137,72 @@
 f (files) %7B%0A
+        const tracks = files.map(extractTrack);%0A
         cons
@@ -2201,36 +2201,37 @@
     const hosted
-File
+Track
 s = processFiles
@@ -2221,34 +2221,36 @@
 ks = process
-Files(file
+Tracks(track
 s, buildFile
@@ -2289,36 +2289,37 @@
 dFileData(hosted
-File
+Track
 s);%0A    %7D%0A%7D);%0A%0Aw
@@ -2472,24 +2472,81 @@
 isFile()) %7B%0A
+                const tracks = %5Bfile%5D.map(extractTrack);%0A
             
@@ -2561,20 +2561,21 @@
 t hosted
-File
+Track
 s = proc
@@ -2581,18 +2581,20 @@
 cess
-Files(file
+Tracks(track
 s, b
@@ -2657,20 +2657,21 @@
 a(hosted
-File
+Track
 s);%0A    

Fix broken client after refactor