import { Injectable } from '@angular/core'

import { Observable, BehaviorSubject, forkJoin, of as observableOf } from 'rxjs'
import { map } from 'rxjs/operators'

// import { Apollo, gql } from 'apollo-angular'

import { ApiService, Project, CategoryRead } from '../../openapi'

// const getSurveyStores = gql`
// query geo_survey_stores {
//     geo_survey_stores {
//         name
//     }
// }
// `

// const getRawSurveyStores = gql`
// query geo_raw_survey_stores {
//     geo_raw_survey_stores {
//         name
//     }
// }
// `

// const getRawSurveyPoints = gql`
// query raw_survey_points ($orig_id: String!) {
//     raw_survey_points(orig_id: $orig_id) {
//         id
//         category
//         date
//         orig_id
//         store
//         status
//         type
//         project
//     }
// }
// `

// const reconciliationItemMutation = gql`
// mutation reconciliationItem(
//         $id: String!,
//         $category: String!
// ) {
//     reconciliationItem(
//         id: $id,
//         category: $category
//     ) {
//         result {
//             message
//         }
//     }
// }
// `

// const changeSurveyPointMutation = gql`
// mutation changeSurveyPointStatus(
//         $id: String!,
//         $status: String!
// ) {
//     changePointStatus(
//         id: $id,
//         status: $status
//     ) {
//         result {
//             message
//         }
//     }
// }
// `

// const deleteSurveyPointMutation = gql`
// mutation deletePoint(
//         $id: String!,
// ) {
//     deletePoint(
//         id: $id,
//     ) {
//         result {
//             message
//         }
//     }
// }
// `


// const categoryMutation = gql`
// mutation categoryMutation(
//     $category: CategoryInput!,
// ) {
//     editCategory(
//         category: $category,
//     ) {
//         result {
//             name
//             _message
//             _mode
//         }
//     }
// }
// `

// const projectMutation = gql`
// mutation projectMutation(
//     $project: ProjectInput!,
// ) {
//     editProject(
//         project: $project,
//     ) {
//         result {
//             id
//         }
//     }
// }
// `

// const categoryDeleteMutation = gql`
// mutation deleteCategory(
//     $name: String!
// ) {
//     deleteCategory(
//         name: $name,
//     ) {
//         result
//     }
// }
// `

// const projectDeleteMutation = gql`
// mutation deleteProject(
//     $id: Int!
// ) {
//     deleteProject(
//         id: $id,
//     ) {
//         result
//     }
// }
// `

// const categoriesQuery = gql`
// query categories {
//     categories {
//         name
//         description
//         group
//         minor_group_1
//         minor_group_2
//         status
//         auto_import
//         model_type
//         long_name
//         symbol
//         mapbox_type_custom
//         mapbox_paint
//         mapbox_layout
//         viewable_role
//         extra
//     }
// }
// `

// const projectsQuery = gql`
// query projects {
//     projects {
//         id
//         name
//         contact_person
//         site
//         date_approved
//         start_date_planned
//         start_date_effective
//         end_date_planned
//         end_date_effective
//     }
// }
// `

// const updateRegistryQuery = gql`
// query updateRegistry {
//     updateRegistry
// }
// `

// const vacuumDbQuery = gql`
// query vacuumDb {
//     vacuumDb
// }
// `

// const runIntegrityCheckQuery = gql`
// query runIntegrityCheck(
//     $integrityCheckId: String!
// ) {
//     integrityCheckRun(
//         integrityCheckId: $integrityCheckId
//     ) {
//         name
//         description
//         dfData
//     }
// }
// `

// const integrityCheckQuery = gql`
// query integrityChecks {
//     integrityChecks {
//         id
//         name
//         description
//     }
// }
// `

export class Store {
    constructor(
        public name: string,
    ) {}
}

// export class Category {
//     constructor(
//         public name: string,
//         public description?: string,
//         public group?: string,
//         public minor_group_1?: string,
//         public minor_group_2?: string,
//         public status?: string,
//         public auto_import?: string,
//         public model_type?: string,
//         public long_name?: string,
//         public symbol?: string,
//         public mapbox_type_custom?: string,
//         public mapbox_paint?: string,
//         public mapbox_layout?: string,
//         public viewable_role?: string,
//         public extra?: string,
//     ) {}
// }

// export class Project {
//     constructor(
//         public id: number,
//         public name: string,
//         public contact_person?: string,
//         public site?: string,
//         public date_approved?: Date,
//         public start_date_planned?: Date,
//         public start_date_effective?: Date,
//         public end_date_planned?: Date,
//         public end_date_effective?: Date,
//     ) {}
// }

export class RawSurveyPoint {
    constructor(
        public id: String,
        public orig_id: String,
        public date: Date,
        public category: String,
        public status: String,
        public store: String,
        public type: String,
        public project: String,
    ) {}
}

export class Field {
    constructor(
        public name: string,
        public type: string,
    ) {}
}

export class DF {
    constructor(
        public fields: Field[],
        public rows: object[]
    ) {}

    get fieldNames() {
        return this.fields.map(f=>f.name)
    }
}

export class IntegrityReport {
    constructor(
        public name: string,
        public description: string,
        public df?: DF,
    ) {}
}

export class IntegrityCheck {
    constructor(
        public id: string,
        public name: string,
        public description: string,
    ) {}
}

@Injectable()
export class AdminManageDataService {
    constructor(
        // private apollo: Apollo,
        public apiService: ApiService,
    ) {}

    getRawSurveyStores(): Observable<Store[]> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.query({
        //     query: getRawSurveyStores,
        // }).pipe(map(
        //     res => res['data']['geo_raw_survey_stores'].map(
        //         (store: object) => new Store(
        //             store['name'],
        //         )
        //     )
        // ))
    }

    getSurveyStores(): Observable<Store[]> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.query({
        //     query: getSurveyStores,
        // }).pipe(map(
        //     res => res['data']['geo_survey_stores'].map(
        //         (store: object) => new Store(
        //             store['name'],
        //         )
        //     )
        // ))
    }

    getRawSurveyPoints(orig_id: string): Observable<RawSurveyPoint[]> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.query({
        //     query: getRawSurveyPoints,
        //     variables: {
        //         orig_id: orig_id
        //     }
        // }).pipe(map(
        //     res => res['data']['raw_survey_points'].map(
        //         (rawSurveyPoint: object) => new RawSurveyPoint(
        //             rawSurveyPoint['id'],
        //             rawSurveyPoint['orig_id'],
        //             rawSurveyPoint['date'],
        //             rawSurveyPoint['category'],
        //             rawSurveyPoint['status'],
        //             rawSurveyPoint['store'],
        //             rawSurveyPoint['type'],
        //             rawSurveyPoint['project'],
        //         )
        //     )
        // ))
    }

    reconcile(item: RawSurveyPoint, category: string): Observable<string> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.mutate({
        //     mutation: reconciliationItemMutation,
        //     variables: {
        //         id: item.id,
        //         category: category
        //     }
        // }).pipe(map(
        //     res => res['data']['reconciliationItem']['result']
        // ))
    }

    changeStatus(item: RawSurveyPoint, status: string): Observable<string> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.mutate({
        //     mutation: changeSurveyPointMutation,
        //     variables: {
        //         id: item.id,
        //         status: status
        //     }
        // }).pipe(map(
        //     res => res['data']['changePointStatus']['result']
        // ))
    }

    delete(item: RawSurveyPoint): Observable<string> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.mutate({
        //     mutation: deleteSurveyPointMutation,
        //     variables: {
        //         id: item.id,
        //     }
        // }).pipe(map(
        //     res => res['data']['deletePoint']['result']
        // ))
    }

    getCategories(): Observable<CategoryRead[]> {
        return this.apiService.getCategoriesApiCategoriesGet()
    }

    getProjects(): Observable<Project[]> {
        return this.apiService.getProjectsApiProjectsGet()
    }

    saveCategory(category: CategoryRead): Observable<object> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.mutate({
        //     mutation: categoryMutation,
        //     variables: {
        //         category: category,
        //     }
        // }).pipe(map(
        //     res => res['data']['editCategory']['result']
        // ))
    }

    deleteCategory(category: CategoryRead): Observable<string> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.mutate({
        //     mutation: categoryDeleteMutation,
        //     variables: {
        //         name: category.name,
        //     }
        // }).pipe(map(
        //     // TODO: distinguish message and error
        //     res => res['data']['deleteCategory']['result']
        // ))
    }

    saveProject(project: Project): Observable<number> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.mutate({
        //     mutation: projectMutation,
        //     variables: {
        //         project: project,
        //     }
        // }).pipe(map(
        //     res => res['data']['editProject']['result']['id']
        // ))
    }

    deleteProject(project: Project): Observable<number> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.mutate({
        //     mutation: projectDeleteMutation,
        //     variables: {
        //         id: project.id,
        //     }
        // }).pipe(map(
        //     res => res['data']['deleteProject']['result']['id']
        // ))
    }

    updateRegistry() {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.query({
        //     query: updateRegistryQuery,
        // }).pipe(map(
        //     res => res['data']['updateRegistry']['result']
        // ))
    }

    vacuumDb(): Observable<boolean> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.query({
        //     query: vacuumDbQuery,
        // }).pipe(map(
        //     res => res['data']['vacuumDb']
        // ))
    }

    runIntegrityCheck(integrityCheck: IntegrityCheck): Observable<IntegrityReport> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.query({
        //     query: runIntegrityCheckQuery,
        //     variables: {
        //         integrityCheckId: integrityCheck.id
        //     }
        // }).pipe(map(
        //     res => {
        //         let report = res['data']['integrityCheckRun']
        //         let dfData = JSON.parse(report['dfData'])
        //         return new IntegrityReport(
        //             report['name'],
        //             report['description'],
        //             dfData && new DF(
        //                 dfData['schema']['fields'].map(
        //                     field => new Field(field['name'], field['type'])
        //                 ),
        //                 dfData['data']
        //             ),
        //         )
        //     }
        // ))
    }

    getIntegrityChecks(): Observable<IntegrityCheck[]> {
        console.warn('Migrate Graphql')
        return observableOf()
        // return this.apollo.query({
        //     query: integrityCheckQuery
        // }).pipe(map(
        //     resp => {
        //         let data = resp['data']['integrityChecks']
        //         return data.map(
        //             (item: object) => new IntegrityCheck(
        //                 item['id'],
        //                 item['name'],
        //                 item['description']
        //             )
        //         )
        //     }
        // ))
    }
}