import { Injectable } from '@angular/core';
import { Http, Response, RequestOptions, URLSearchParams } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';

import { Device } from '../inventory/device';
import { Session } from './session';

@Injectable()
export class SessionsService{
    public sessions: Session[];
    public activeSession;

    constructor(private http: Http) {
        this.activeSession = localStorage.getItem('activeSession');
        if (!this.activeSession) {
            this.activeSession = "";
        }
        this.checkSessions();
    }

    storeData() {
        localStorage.setItem('sessions', JSON.stringify(this.sessions));
    }

    loadData() {
        this.sessions = JSON.parse(localStorage.getItem('sessions'));
    }

    getActiveSession(key: string = this.activeSession): Session {
        if (!key) {
            return null;
        }
        for (let i = this.sessions.length; i > 0; i--) {
            if (this.sessions[i - 1].key == key) {
                return this.sessions[i - 1];
            }
        }
        return null;
    }

    changeActiveSession(key: string): Session {
        if (!this.activeSession) {
            return null;
        }
        let result = this.getActiveSession(key);
        if (result) {
            this.activeSession = key;
            localStorage.setItem('activeSession', this.activeSession);
        }
        return result;
    }

    checkSessions() {
        this.loadData();
        if (!this.sessions) {
            this.sessions = [];
        } else {
            /* verify that the sessions are still active */
            for (let i = this.sessions.length; i > 0; i--) {
                this.alive(this.sessions[i - 1].key).subscribe(resp => {
                    if (!resp['success']) {
                        if (this.activeSession && this.sessions[i - 1].key == this.activeSession) {
                            /* active session is not alive - select new active session
                             * as the one on the left from the current one, if there
                             * is no one, choose the one on the right */
                            if (i > 1) {
                                this.activeSession = this.sessions[i - 2].key;
                            } else if (this.sessions.length > i) {
                                this.activeSession = this.sessions[i].key;
                            } else {
                                this.activeSession = "";
                            }
                        }
                        this.sessions.splice(i - 1, 1);
                    }
                });
            }
        }
    }

    createModificationsRecord(path) {
        let activeSession = this.getActiveSession();
        if (!activeSession.modifications) {
            activeSession.modifications = {};
        }

        if (!(path in activeSession.modifications)) {
            activeSession.modifications[path] = {};
        }
        return activeSession.modifications[path];
    }

    getModificationsRecord(path) {
        let activeSession = this.getActiveSession();
        if (!activeSession.modifications) {
            return null;
        }

        if (!(path in activeSession.modifications)) {
            return null;
        }
        return activeSession.modifications[path];
    }

    removeModificationsRecord(path = null) {
        let activeSession = this.getActiveSession();
        if (!activeSession.modifications) {
            return;
        }

        if (path && (path in activeSession.modifications)) {
            delete activeSession.modifications[path];
        }

        if (!Object.keys(activeSession.modifications).length) {
            delete activeSession.modifications;
        }
    }

    checkValue(key: string, path: string, value: string): Observable<string[]> {
        let params = new URLSearchParams();
        params.set('key', key);
        params.set('path', path);
        params.set('value', value);
        let options = new RequestOptions({ search: params });
        return this.http.get('/netopeer/session/schema/checkvalue', options)
            .map((resp: Response) => resp.json())
            .catch((err: Response | any) => Observable.throw(err));
    }

    childrenSchemas(key: string, path: string, node = null) {
        let params = new URLSearchParams();
        params.set('key', key);
        params.set('path', path);
        params.set('relative', 'children');
        let options = new RequestOptions({ search: params });
        return this.http.get('/netopeer/session/schema', options)
            .map((resp: Response) => {
                let result = resp.json();
                console.log(result)
                if (result['success'] && node) {
                    for (let iter of node['children']) {
                        if (iter['deleted'] || (iter['info']['type'] & 0x18)) {
                            /* ignore deleted nodes and nodes that can be instantiated multiple times */
                            continue;
                        }
                        for (let index in result['data']) {
                            if (!result['data'][index]['config'] ||
                                    (result['data'][index]['name'] == iter['info']['name'] && result['data'][index]['module'] == iter['info']['module'])) {
                                /* 1. read-only node */
                                /* 2. the node is already instantiated */
                                result['data'].splice(index, 1);
                                break;
                            }
                        }
                    }
                }
                if (result['success']) {
                    return result['data'];
                } else {
                    return [];
                }
            }).toPromise();
    }

    alive(key: string): Observable<string[]> {
        let params = new URLSearchParams();
        params.set('key', key);
        let options = new RequestOptions({ search: params });
        return this.http.get('/netopeer/session/alive', options)
            .map((resp: Response) => resp.json())
            .catch((err: Response | any) => Observable.throw(err));
    }

    getCpblts(key: string): Observable<string[]> {
        let params = new URLSearchParams();
        params.set('key', key);
        let options = new RequestOptions({ search: params });
        return this.http.get('/netopeer/session/capabilities', options)
            .map((resp: Response) => resp.json())
            .catch((err: Response | any) => Observable.throw(err));
    }

    setDirty(node) {
        let activeSession = this.getActiveSession();
        if (!activeSession.modifications) {
            return;
        }

        if (node['path'] in activeSession.modifications) {
            node['dirty'] = true;
            if (activeSession.modifications[node['path']]['type'] == 'change') {
                activeSession.modifications[node['path']]['original'] = node['value'];
            }
            node['value'] = activeSession.modifications[node['path']]['value']; 
        }
        /* recursion */
        if ('children' in node) {
            for (let child of node['children']) {
                this.setDirty(child);
            }
        }
    }

    rpcGetSubtree(key: string, all: boolean, path: string = ""): Observable<string[]> {
        let params = new URLSearchParams();
        params.set('key', key);
        params.set('recursive', String(all));
        if (path.length) {
            params.set('path', path);
        }
        let options = new RequestOptions({ search: params });
        return this.http.get('/netopeer/session/rpcGet', options)
            .map((resp: Response) => {
                let result = resp.json();
                //console.log(result);
                if (result['success']) {
                    if (path.length) {
                        for (let iter of result['data']['children']) {
                            this.setDirty(iter);
                        }
                    } else {
                        for (let iter of result['data']) {
                            this.setDirty(iter);
                        }
                    }
                }
                return result;
            })
            .catch((err: Response | any) => Observable.throw(err));
    }

    close(key: string) {
        let params = new URLSearchParams();
        params.set('key', key);
        let options = new RequestOptions({search: params});
        return this.http.delete('/netopeer/session', options)
            .map((resp: Response) => resp.json())
            .do(resp => {
                if (resp['success']) {
                    this.sessions.splice(this.sessions.findIndex((s: Session) => s.key == key), 1);
                    if (key == this.activeSession) {
                        if (this.sessions.length) {
                            this.activeSession = this.sessions[0].key;
                        } else {
                            this.activeSession = ""
                        }
                    }
                    this.storeData();
                    localStorage.setItem('activeSession', this.activeSession);
                }
            })
            .catch((err: Response | any) => Observable.throw(err));
    }

    connect(dev: Device) {
        let options = null; // = new RequestOptions({body: JSON.stringify({'id': dev.id})});
        if (dev.id) {
            options = new RequestOptions({body: JSON.stringify({'id': dev.id})});
        } else {
            options = new RequestOptions({body: JSON.stringify({'device': {'hostname': dev.hostname, 'port': dev.port, 'username': dev.username, 'password': dev.password}})});
        }
        return this.http.post('/netopeer/session', null, options)
            .map((resp: Response) => resp.json())
            .do(resp => {
                if (resp['success']) {
                    this.sessions.push(new Session(resp['session-key'], dev));
                    this.activeSession = resp['session-key'];
                    this.storeData();
                    localStorage.setItem('activeSession', this.activeSession);
                }
            })
            .catch((err: Response | any) => Observable.throw(err))
    }
}
