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();
    }

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

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

    checkSessions() {
        this.sessions = JSON.parse(localStorage.getItem('sessions'));
        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);
                    }
                });
            }
        }
    }

    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));
    }

    rpcGet(key: string): Observable<string[]> {
        let params = new URLSearchParams();
        params.set('key', key);
        let options = new RequestOptions({ search: params });
        return this.http.get('/netopeer/session/rpcGet', options)
            .map((resp: Response) => resp.json())
            .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 = ""
                        }
                    }
                    localStorage.setItem('sessions', JSON.stringify(this.sessions));
                    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, "", "", false, false));
                    this.activeSession = resp['session-key'];
                    localStorage.setItem('sessions', JSON.stringify(this.sessions));
                    localStorage.setItem('activeSession', this.activeSession);
                }
            })
            .catch((err: Response | any) => Observable.throw(err))
    }
}
