import { Injectable } from "@angular/core";
import { Observable } from "rxjs/Observable";
import { Observer } from "rxjs/Observer";
import PouchDB from "pouchdb";

import * as PouchFind from "pouchdb-find";

import "rxjs/add/observable/throw";
import "rxjs/add/observable/fromPromise";
import "rxjs/add/observable/from";
import "rxjs/add/operator/concatMap";

PouchDB.plugin(PouchFind);

@Injectable()
export class PouchService {

    pouchDB: any;

    constructor() {
        this.initialize();
    }

    /**
     *
     */
    private initialize(): Observable<any> {
        this.pouchDB = new PouchDB("odoo", {
            auto_compaction: true
        });

        return Observable.fromPromise(this.pouchDB.createIndex({
            index: {
                fields: ['type']
            }
        }));
    }

    /**
     *
     */
    save(data: any): Observable<any> {
        if (!data.type) {
            return Observable.throw("Error: Cannot save data without type");
        }

        delete data.__last_update;
        

        return Observable.fromPromise(this.pouchDB.post(data));
    }

    /**
     *
     */
    remove(data: any): Observable<any> {
        if (!data._id || !data._rev) {
            return Observable.throw("Error: Cannot remove data without id or rev");
        }

        return Observable.fromPromise(this.pouchDB.remove(data));
    }

    /**
     *
     */
    removeAll(type: string): Observable<any> {
        return this.getAll(type).concatMap(result => Observable.from(result.docs)).concatMap(doc => this.remove(Object.assign(doc, { _deleted: true })));
    }

    /**
     *
     */
    get(data: any): Observable<any> {
        if (!data._id) {
            return Observable.throw("Error: Cannot get data without id");
        }

        return Observable.fromPromise(this.pouchDB.get(data._id));
    }

    /**
     *
     */
    getAll(type: string): Observable<any> {
        return Observable.fromPromise(this.pouchDB.find({
            selector: {
                type: {
                    $eq: type
                }
            }
        }));
    }

    /**
     *
     */
    destroy(): Observable<any> {
        return Observable.fromPromise(this.pouchDB.destroy());
    }

    /**
     *
     */
    destroyAndInitialize() {
        return this.destroy().concat(this.initialize());
    }
}
