import { Injectable } from '@angular/core'
import { HttpClient } from '@angular/common/http'
import { Observable, Subject, of } from 'rxjs'
import { map } from 'rxjs/operators'

import { WebsocketService } from '../../_services/websocket.service'

export class Feature {
    constructor(
        public store: string,
        public id: string,
    ) {}
}

export class Job {
    constructor(
        public id: string,
        public name: string,
        public type: string,
        public schedParams: string,
        public nextRunTime: Date,
        public lastRun: JobEvent,
        public features?: Feature[],
    ) {}

    setLastEvent(event: JobEvent) {
        this.lastRun = event
        this.nextRunTime = event.nextRunTime
    }
}

export class JobEvent {
    constructor(
        public jobId: string,
        public time: Date,
        public status: string,
        public msg: string,
        public nextRunTime: Date,
    ) {}
}

// const timeQuery = gql`
// query scheduler_time {
//     scheduler_time
// }
// `

// const jobsQuery = gql`
// query scheduler_jobs {
//     scheduler_jobs {
//         id
//         name
//         type
//         schedParams
//         nextRunTime
//         lastRun {
//             time
//             status
//             msg
//             nextRunTime
//         }
//         features {
//             store
//             id_
//         }
//     }
// }`

// const jobsEventsSubscription = gql`
// subscription {
//     jobEvent {
//         jobId
//         time
//         status
//         msg
//         nextRunTime
//     }
// }
// `

@Injectable()
export class SchedulerService {
    //jobsEventsSubscriptionRef: QueryRef<any>
    constructor(
        private wsService: WebsocketService,
        private _http: HttpClient,
        // private apollo: Apollo
    ) {
        /*
        this.jobsEventsSubscriptionRef = apollo.watchQuery({
            query: jobsEventsSubscription,
            notifyOnNetworkStatusChange: true
        })
        this.jobsEventsSubscriptionRef.valueChanges.subscribe(
            val => console.log(val)
        )
        */
    }

    connect(openObserver?: Subject<any>, closeObserver?: Subject<any>) {
        const hostname = window.location.hostname
        const port = window.location.port
        let protocol = window.location.protocol == 'https:' ? 'wss:' : 'ws:'
        this.wsService.connect(
            protocol + '//' + hostname + ':' + port + '/_sched/events',
            openObserver,
            closeObserver
        )
        this.wsService.ws.pipe(map(
            foo => console.log(foo),
        ))
        return this.wsService.ws
    }

    disconnect() {
        this.wsService.disconnect()
    }

    getTime(): Observable<Date> {
        return this._http.get('/sched/time').pipe(map(
            (result: string) => new Date(result)
        ))
    }

    getJobs(): Observable<Job[]> {
        return this._http.get<Object[]>('/sched/jobs').pipe(map(
            result => result && result.map(
                job => new Job(
                    job['id'],
                    job['name'],
                    job['type'],
                    job['schedParams'],
                    job['nextRunTime'],
                    job['lastRun'] || new JobEvent(
                        job['id'],
                        undefined,
                        'undef',
                        'Pending display update',
                        undefined
                    ),
                    job['features'].map(
                        f => new Feature(
                            f['store'],
                            f['id_'],
                        )
                    )
                )
            )
        ))
    }

    getJobEvents(): Observable<JobEvent> {
        // Open a websocket connection for job event updates
        this.wsService.subscribe('jobEvent')
        return of(new JobEvent('',undefined,'','',undefined))
        // return this.apollo.subscribe({
        //     query: jobsEventsSubscription,
        // },
        // ).pipe(map(
        //     result => {
        //         let jobEvent = result['data']['jobEvent']
        //         return new JobEvent(
        //             jobEvent['jobId'],
        //             jobEvent['time'],
        //             jobEvent['status'],
        //             jobEvent['msg'],
        //             jobEvent['nextRunTime'],
        //         )
        //     }
        // ))
    }
}