import { Injectable } from "@angular/core";
import { Observable } from "rxjs/Observable";
import { Observer } from "rxjs/Observer";
import { Subscription } from "rxjs/Subscription";
import { Diagnostic, Camera, BarcodeScanner, Contact, Contacts, ContactName, ContactField, ContactAddress, CallNumber, Geolocation, LaunchNavigator, LaunchNavigatorOptions, Shake, Vibration } from "ionic-native";

@Injectable()
export class PhoneProvider {

    private cameraOptions = {
        sourceType: Camera.PictureSourceType.CAMERA,
        destinationType: Camera.DestinationType.DATA_URL,
        correctOrientation: true,
        saveToPhotoAlbum: false,
        targetHeight: 300,
        targetWidth: 300
    };

    watcher: Subscription;

    constructor() { }

    /**
     *
     */
    openCamera(from: string): Observable<any> {
        this.cameraOptions.sourceType = from == "album" ? Camera.PictureSourceType.SAVEDPHOTOALBUM : this.cameraOptions.sourceType;

        return Observable.create((observer: Observer<any>) => {
            Camera.getPicture(this.cameraOptions).then(image => { 
                observer.next(image);
                observer.complete();
            }).catch(e => observer.error(e));
        });
    }

    /**
     *
     */
    scanBarcode(): Observable<any> {
        return Observable.create((observer: Observer<any>) => {
            BarcodeScanner.scan().then(barcode => {
                observer.next(barcode);
                observer.complete();
            }).catch(e => observer.error(e));
        });
    }

    /**
     *
     */
    saveContact(name: string, numbers: Array<any>, email?: string, addresses?: Array<any>): Observable<any> {
        return Observable.create((observer: Observer<any>) => { 
            let contact = Contacts.create();
            contact.displayName.concat(name);

            for (let i = 0; i < numbers.length; i++) {
                contact.phoneNumbers.push(new ContactField('mobile', numbers[i]));
            }
            
            if (email) {
                contact.emails.push(new ContactField("email", email));
            }
            
            if (addresses) {
                for (let i = 0; i < addresses.length; i++) {
                    contact.addresses.push(new ContactAddress());
                }
            }

            contact.save().then(() => { 
                observer.complete();
            }, e => observer.error(e));
        });
    }   

    /**
     *
     */
    call(numberToCall: string): Observable<any> {
        return Observable.create((observer: Observer<any>) => { 
            CallNumber.callNumber(numberToCall, true).then(() => observer.complete()).catch(e => observer.error(e));
        });
    }

    /**
     *
     */
    getGpsStatus(): Observable<any> {
        return Observable.create((observer: Observer<any>) => { 
            Diagnostic.isGpsLocationEnabled().then(status => {
                observer.next(status);
                observer.complete();
            });
        });
    }

    /**
     *
     */
    switchToGpsSettings(): void {
        Diagnostic.switchToLocationSettings();
    }

    /**
     *
     */
    getCurrentPosition(): Observable<any> {
        return Observable.create((observer: Observer<any>) => {
            Geolocation.getCurrentPosition().then(position => {
                observer.next(position);
                observer.complete();
            }).catch(e => observer.error(e));
        });
    }

    /**
     *
     */
    navigate(latitude: number, longitude: number): Observable<any> {
        return Observable.create((observer: Observer<any>) => {
            LaunchNavigator.navigate([latitude, longitude]).then(s => { 
                observer.next(s);
                observer.complete();
            }).catch(e => observer.error(e));
        });
    }

    /**
     *
     */
    enableShakeWatcher(): Observable<any> {
        this.disableShakeWatcher();

        return Observable.create((observer: Observer<any>) => {
            this.watcher = Shake.startWatch(40).subscribe(() => { 
                observer.next("ok");
            });
        });
    }

    /**
     *
     */
    disableShakeWatcher(): void {
        if (this.watcher && !this.watcher.closed) {
            this.watcher.unsubscribe();
        }
    }

    /**
     *
     */
    vibrate(): void {
        Vibration.vibrate(500);
    }
}