import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';

import { environment } from '../../../environments/environment';
import { ApiService } from './api.service';
import { UtilsService } from './utils.service';

import { UserConfig } from '../models/user-config.model';
import { SearchUserConfig } from './../models/search-user-config.model';
import { SearchRequest } from '../models/search-request.model';

@Injectable()
export class SearchService {

    constructor(
        private apiService: ApiService,
        private utilsService: UtilsService,
    ) {

    }

    /**
     * Use this function for any kind of search service call.
     */
    getObjects(serviceName: string, queryType: string, queryParams, assocs: String[], attribProfile: string, sort: string, resultsFrom: Number, resultsTo: Number, additionalParams: any={}): Observable<any> {
        return this.getObjectsWithDocument(serviceName, queryType, queryParams, assocs, attribProfile, sort, resultsFrom, resultsTo, null, false, additionalParams);
    }

    getObjectsWithDocument(serviceName: string, queryType: string, queryParams, assocs: String[], attribProfile: string, sort: string,
        resultsFrom: Number, resultsTo: Number, generateDocument: string, excelExport: boolean, additionalParams: any={}): Observable<any> {
        let params: any = {
            environment: environment.envName,    //Fetch this from environment e.g. environment.envName
            queryType: queryType,
            queryParams: this.utilsService.replaceObjectsWithIDIfExists(queryParams),
            assocs: assocs,
            excelExport: excelExport
        }

        if (generateDocument) {
            params.generateDocument = generateDocument;
        }

        if (attribProfile) {
            params.attribs = attribProfile;
        }

        if (sort) {
            params.sort = sort;
        }

        if (resultsFrom || resultsFrom === 0) {
            params.ResultsFrom = resultsFrom;
        }

        if (resultsTo || resultsTo === 0) {
            params.ResultsTo = resultsTo;
        }

        if(additionalParams){
            for(let key in additionalParams){
                params[key] =   additionalParams[key];
            }
        }

        if (generateDocument || excelExport) {
            return this.apiService.postBlobRequest("svc/" + serviceName, params);
        } else {
            return this.apiService.post("svc/" + serviceName, params);
        }
    }

    getObjectById(serviceName: string, id: string, assocs: String[], additionalParams: any={}): Observable<any> {
        return this.getObjects(serviceName, "ByID", { id: [id] }, assocs, null, null, null, null, additionalParams);
    }

    downloadDocument(serviceName: string, id: string, generateDocument: string, additionalParams: any={}): Observable<any> {
        return this.getObjectsWithDocument(serviceName, "ByID", { id: [id] }, [], null, null, null, null, generateDocument, false, additionalParams);
    }

    downloadExcel(serviceName: string, queryType: string, queryParams, assocs: String[], attribProfile: string, sort: string, resultsFrom: Number, resultsTo: Number, additionalParams: any={}): Observable<any> {
        return this.getObjectsWithDocument(serviceName, queryType, queryParams, assocs, attribProfile, sort, resultsFrom, resultsTo, null, true, additionalParams);
    }

    searchAndSaveSearchRequest(serviceName: string, queryType: string, queryParams, assocs: String[], attribProfile: string, sort: string, resultsFrom: Number, resultsTo: Number, searchName: string, saveSearch: boolean, additionalParams: any={}): Observable<any> {
        return this.getObjects(serviceName, queryType, queryParams, assocs, attribProfile, sort, resultsFrom, resultsTo, additionalParams)
            .map(
                data => {
                    if (saveSearch) {
                        this.saveSearchRequest(new SearchRequest(serviceName, queryType, queryParams, assocs, attribProfile, sort, resultsFrom, resultsTo), searchName).subscribe(
                            saveRes => {

                            },
                            error => {
                                console.log("Error occured when saving search data for " + serviceName);
                            }
                        );
                    }
                    return data;
                }
            );
    }

    saveSearchRequest(searchRequest: SearchRequest, searchName: string): Observable<any> {
        let userConfig: UserConfig = new UserConfig();

        userConfig.Type = searchName;
        userConfig.Data = JSON.stringify(searchRequest);

        return this.utilsService.processObjects("SaveUserConfig", userConfig);
    }

    getLastSearchRequest(searchName: string, onlyForToday: boolean = false): Observable<SearchRequest> {
        let searchUserConfig: SearchUserConfig = new SearchUserConfig();

        searchUserConfig.Type = searchName;
        searchUserConfig.LatestRecordOnly = true;

        return this.getObjects("UserConfigs", "All", searchUserConfig, [], null, null, null, null).map(
            data => {
                let results: UserConfig[] = this.utilsService.convertResponseToObjects(data, []);

                if (results.length > 0 && (!onlyForToday || (this.utilsService.getToday() < new Date(results[0]['ObjectCreated'])))) {
                    return JSON.parse(results[0].Data) as SearchRequest;
                }
                return null;
            }
        );
    }
}