import { Injectable } from '@angular/core';
import { Event, EventToApproveEdit } from '../models/event.model';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable, from } from 'rxjs';
import { environment } from 'src/environments/environment';
import { AuthService } from '../services/auth.service';
import { UserSession } from '../models/user.model';
import { EventList } from '../models/agenda/AgendaEventList';
import { ChangeProfileService } from './change-profile.service';
import { OfflineManagerService } from 'src/app/services/offline-manager.service';
import { catchError } from "rxjs/operators";
import { Storage } from '@ionic/storage';
import { BackgroundService } from 'src/app/services/background.service';


@Injectable({
  providedIn: 'root'
})
export class EventsService {

  authheader = {};
  loggeduser: UserSession;
  headers: HttpHeaders;

  headersPrOficial: HttpHeaders;
  headersPrPessoal: HttpHeaders;

  headersMdOficial: HttpHeaders;
  headersMdPessoal: HttpHeaders;

  headersSharedOficial: HttpHeaders;
  headersSharedPessoal: HttpHeaders;

  constructor(
    private http: HttpClient,
    public user: AuthService,
    private changeProfileService: ChangeProfileService,
    private offlinemanager: OfflineManagerService,
    private storage: Storage,
    private backgroundservice: BackgroundService) {

    this.loggeduser = this.user.ValidatedUser;

    this.headersMdOficial = new HttpHeaders();
    this.headersMdPessoal = new HttpHeaders();

    this.headersPrOficial = new HttpHeaders();
    this.headersPrPessoal = new HttpHeaders();

    this.headersSharedOficial = new HttpHeaders();
    this.headersSharedPessoal = new HttpHeaders();


    this.setHeader()
    this.changeProfileService.registerCallback(() => {
      this.loggeduser = this.user.ValidatedUser;
      this.setHeader()
    })

  }

  setHeader() {

    if (this.loggeduser) {
      if (this.loggeduser.Profile == 'MDGPR') {

        this.loggeduser.OwnerCalendars.forEach(calendar => {
          if (calendar.CalendarName == 'Oficial') {
            this.headersMdOficial = this.headersMdOficial.set('Authorization', this.loggeduser.BasicAuthKey);
            this.headersMdOficial = this.headersMdOficial.set('CalendarId', calendar.CalendarId);
            this.headersMdOficial = this.headersMdOficial.set('CalendarRoleId', calendar.CalendarRoleId);
          }
          else if (calendar.CalendarName == 'Pessoal') {
            this.headersMdPessoal = this.headersMdPessoal.set('Authorization', this.loggeduser.BasicAuthKey);
            this.headersMdPessoal = this.headersMdPessoal.set('CalendarId', calendar.CalendarId);
            this.headersMdPessoal = this.headersMdPessoal.set('CalendarRoleId', calendar.CalendarRoleId);

          }
        });

        this.loggeduser.SharedCalendars.forEach(sharedCalendar => {
          if (sharedCalendar.CalendarName == 'Oficial') {
            this.headersSharedOficial = this.headersSharedOficial.set('Authorization', this.loggeduser.BasicAuthKey);
            this.headersSharedOficial = this.headersSharedOficial.set('CalendarId', sharedCalendar.CalendarId);
            this.headersSharedOficial = this.headersSharedOficial.set('CalendarRoleId', sharedCalendar.CalendarRoleId);
          }
          else if (sharedCalendar.CalendarName == 'Pessoal') {
            this.headersSharedPessoal = this.headersSharedPessoal.set('Authorization', this.loggeduser.BasicAuthKey);
            this.headersSharedPessoal = this.headersSharedPessoal.set('CalendarId', sharedCalendar.CalendarId);
            this.headersSharedPessoal = this.headersSharedPessoal.set('CalendarRoleId', sharedCalendar.CalendarRoleId);
          }
        });
      }
      else if (this.loggeduser.Profile == 'PR') {

        this.loggeduser.OwnerCalendars.forEach(calendar => {
          if (calendar.CalendarName == 'Oficial') {
            this.headersPrOficial = this.headersPrOficial.set('Authorization', this.loggeduser.BasicAuthKey);
            this.headersPrOficial = this.headersPrOficial.set('CalendarId', calendar.CalendarId);
            this.headersPrOficial = this.headersPrOficial.set('CalendarRoleId', calendar.CalendarRoleId);
          }
          else if (calendar.CalendarName == 'Pessoal') {
            this.headersPrPessoal = this.headersPrPessoal.set('Authorization', this.loggeduser.BasicAuthKey);
            this.headersPrPessoal = this.headersPrPessoal.set('CalendarId', calendar.CalendarId);
            this.headersPrPessoal = this.headersPrPessoal.set('CalendarRoleId', calendar.CalendarRoleId);

          }
        });
      }

      this.headers = new HttpHeaders();
      this.headers = this.headers.set('Authorization', this.loggeduser.BasicAuthKey);
    }
  }

  /* getAllEvents(startdate:string, enddate:string): Observable<Event[]>{
    const geturl = environment.apiURL + 'calendar/GetAllEvents';
    let params = new HttpParams();

    params = params.set("StartDate", startdate);
    params = params.set("EndDate", enddate);

    let options = {
      headers: this.headers,
      params: params
    };
    return this.http.get<Event[]>(`${geturl}`, options);
  } */


  getAllPrOficialEvents(startdate: string, enddate: string): Observable<EventList[]> {
    let geturl = environment.apiURL + 'calendar/pr';
    geturl = geturl.replace('/V4/', '/V5/')

    let params = new HttpParams();

    params = params.set("Start", startdate);
    params = params.set("End", enddate);

    let options = {
      headers: this.headersPrOficial,
      params: params
    };
    return this.http.get<EventList[]>(`${geturl}`, options);
  }

  getAllPrPessoalEvents(startdate: string, enddate: string): Observable<EventList[]> {
    let geturl = environment.apiURL + 'calendar/pr';
    geturl = geturl.replace('/V4/', '/V5/')

    let params = new HttpParams();

    params = params.set("Start", startdate);
    params = params.set("End", enddate);

    let options = {
      headers: this.headersPrPessoal,
      params: params
    };
    return this.http.get<EventList[]>(`${geturl}`, options);
  }

  async getAllPrEvents(startdate: string, enddate: string): Promise<EventList[]> {
    let prO = await this.getAllPrOficialEvents(startdate, enddate).toPromise();
    let prP = await this.getAllPrPessoalEvents(startdate, enddate).toPromise();
    const resFinal = prO.concat(prP);
    return new Promise(resolve => {
      return resolve(resFinal)
    })
  }

  getAllMdOficialEvents(startdate: string, enddate: string): Observable<EventList[]> {
    let geturl = environment.apiURL + 'calendar/md';

    let params = new HttpParams();

    params = params.set("Start", startdate);
    params = params.set("End", enddate);

    let options = {
      headers: this.headersMdOficial,
      params: params
    };
    return this.http.get<EventList[]>(`${geturl}`, options);
  }

  getAllMdPessoalEvents(startdate: string, enddate: string): any {
    let geturl = environment.apiURL + 'calendar/md';

    let params = new HttpParams();

    params = params.set("Start", startdate);
    params = params.set("End", enddate);

    let options = {
      headers: this.headersMdPessoal,
      params: params
    };
    return this.http.get<any>(`${geturl}`, options)
  }

  async getAllMdEvents(startdate: string, enddate: string) {
    let prO = await this.getAllMdOficialEvents(startdate, enddate).toPromise();
    let prP = await this.getAllMdPessoalEvents(startdate, enddate).toPromise();
    const resFinal = prO.concat(prP);
    return new Promise(resolve => {
      return resolve(resFinal)
    });
  }

  async getAllSharedEvents(startdate: string, enddate: string) {
    let prO = await this.getAllSharedOficialEvents(startdate, enddate).toPromise();
    let prP = await this.getAllSharedPessoalEvents(startdate, enddate).toPromise();
    const resFinal = prO.concat(prP);

    return new Promise(resolve => {
      return resolve(resFinal)
    });
  }



  getAllSharedOficialEvents(startdate: string, enddate: string): Observable<Event[]> {
    let geturl = environment.apiURL + 'calendar/pr';
    geturl = geturl.replace('/V4/', '/V5/')

    let params = new HttpParams();

    params = params.set("Start", startdate);
    params = params.set("End", enddate);

    let options = {
      headers: this.headersSharedOficial,
      params: params
    };
    console.log(options);

    return this.http.get<Event[]>(`${geturl}`, options);
  }

  getAllSharedPessoalEvents(startdate: string, enddate: string): Observable<Event[]> {
    let geturl = environment.apiURL + 'calendar/pr';
    geturl = geturl.replace('/V4/', '/V5/')

    let params = new HttpParams();

    params = params.set("Start", startdate);
    params = params.set("End", enddate);

    let options = {
      headers: this.headersSharedPessoal,
      params: params
    };
    return this.http.get<Event[]>(`${geturl}`, options);
  }


  getRecurrenceTypes(): any {
    const geturl = environment.apiURL + 'Calendar/RecurrenceTypes';
    let options = {
      headers: this.headers,
    };
    return this.http.get<any>(`${geturl}`, options);
  }


  getEvents(calendarname: string, startdate: string, enddate: string): Observable<Event[]> {
    const geturl = environment.apiURL + 'calendar/GetEvents';
    let params = new HttpParams();

    params = params.set("CalendarName", calendarname);
    params = params.set("StartDate", startdate);
    params = params.set("EndDate", enddate);

    let options = {
      headers: this.headers,
      params: params
    };
    return this.http.get<Event[]>(`${geturl}`, options);
  }

  getEvent(eventid: string): Observable<Event> {
    let geturl = environment.apiURL + 'calendar/GetEvent';
    let params = new HttpParams();

    params = params.set("EventId", eventid);

    let options = {
      headers: this.headers,
      params: params
    };

    return this.http.get<Event>(`${geturl}`, options);
  }

  putEvent(event: Event, conflictResolutionMode: number, sendInvitationsOrCancellationsMode: number, sharedagenda: string): Observable<Event> {
    const puturl = environment.apiURL + 'calendar/' + ((sharedagenda != '') ? sharedagenda : 'PutEvent');

    let params = new HttpParams();

    params = params.set("conflictResolutionMode", conflictResolutionMode.toString());
    params = params.set("sendInvitationsOrCancellationsMode", sendInvitationsOrCancellationsMode.toString());

    let options = {
      headers: this.headers,
      params: params
    };

    return this.http.put<Event>(`${puturl}`, event, options)
  }

  editEvent(event: Event, conflictResolutionMode: number, sendInvitationsOrCancellationsMode: number): Observable<Event> {
    let arrayReq = [];
    arrayReq.push(event);
    const puturl = environment.apiURL + 'calendar/PutEvent';
    let params = new HttpParams();

    params = params.set("conflictResolutionMode", conflictResolutionMode.toString());
    params = params.set("sendInvitationsOrCancellationsMode", sendInvitationsOrCancellationsMode.toString());
    params.set('CalendarId', event.CalendarId)
    params.set('CalendarName', event.CalendarName)
    this.headers['CalendarId'] = event.CalendarId
    this.headers['CalendarName'] = event.CalendarName

    if (event.CalendarName == 'Oficial') {
      if (this.loggeduser.Profile == 'MDGPR') {
        this.headers = this.headersMdOficial;
      }
      else if (this.loggeduser.Profile == 'PR') {
        this.headers = this.headersPrOficial;
      }
    }
    else {
      if (this.loggeduser.Profile == 'MDGPR') {
        this.headers = this.headersMdPessoal;
      }
      else if (this.loggeduser.Profile == 'PR') {
        this.headers = this.headersPrPessoal;
      }
    }

    let options = {
      headers: this.headers,
      params: params
    };

    return this.http.put<Event>(`${puturl}`, event, options).pipe(
      catchError(err => {
        console.log('Event edit saved offline')
        this.offlinemanager.storeRequestData('eventEdit', arrayReq);
        throw new Error(err);
      })
    )
  }

  changeAgenda(body: any) {
    const puturl = environment.apiURL + 'Calendar/MoveEvent';
    let options = {
      headers: this.headers,
    };
    return this.http.post<any>(`${puturl}`, body, options);
  }

  /* postEvent(event:Event, calendarName:string, sharedagenda:string)
  {
    const puturl = environment.apiURL + 'calendar/' + ((sharedagenda != '') ? sharedagenda : 'PostEvent');
    let params = new HttpParams();

    params = params.set("CalendarName", calendarName);

    let options = {
      headers: this.headers,
      params: params
    };

    return this.http.post<Event>(`${puturl}`, event, options)
  } */

  postEventMd(event: Event, calendarName: string) {
    const puturl = environment.apiURL + 'calendar/md';
    let params = new HttpParams();

    params = params.set("CalendarName", calendarName);

    let options: any;
    switch (calendarName) {
      case 'Oficial':
        console.log(calendarName);
        options = {
          headers: this.headersMdOficial,
          params: params
        };
        break;

      case 'Pessoal':
        console.log(calendarName);
        options = {
          headers: this.headersMdPessoal,
          params: params
        };
        break;
    }
    console.log(options);
    return this.http.post<string>(`${puturl}`, event, options)
  }

  postEventPr(event: Event, calendarName: string) {
    const puturl = environment.apiURL + 'calendar/pr';
    let params = new HttpParams();

    params = params.set("CalendarName", calendarName);

    let options: any;
    switch (calendarName) {
      case 'Oficial':
        console.log(calendarName);
        options = {
          headers: this.headersPrOficial,
          params: params
        };
        break;

      case 'Pessoal':
        console.log(calendarName);
        options = {
          headers: this.headersPrPessoal,
          params: params
        };
        break;
    }

    return this.http.post<string>(`${puturl}`, event, options)
  }

  deleteEvent(eventid: string, eventDeleteType: number, calendarName: string) {
    let arrayReq = [];
    let Object = {
      eventid: eventid,
      eventDeleteType: eventDeleteType,
      calendarName: calendarName
    }
    arrayReq.push(Object)
    const puturl = environment.apiURL + 'calendar/DeleteEvent';
    let params = new HttpParams();

    params = params.set("EventId", eventid);
    // 0 for occurence and 1 for serie (delete all events)
    params = params.set("eventDeleteType", eventDeleteType.toString());

    let options;

    switch (this.loggeduser.Profile) {
      case 'MDGPR':
        if (calendarName == 'Pessoal') {
          options = {
            headers: this.headersMdPessoal,
            params: params
          };
        }
        else if (calendarName == 'Oficial') {
          options = {
            headers: this.headersMdOficial,
            params: params
          };
        }
        break;
      case 'PR':
        if (calendarName == 'Pessoal') {
          options = {
            headers: this.headersPrPessoal,
            params: params
          };
        }
        else if (calendarName == 'Oficial') {
          options = {
            headers: this.headersPrOficial,
            params: params
          };
        }
        break;
    }

    return this.http.delete(`${puturl}`, options).pipe(
      catchError(err => {
        console.log('Event edit saved offline')
        this.offlinemanager.storeRequestData('eventDelete', arrayReq);
        throw new Error(err);
      })
    )
  }
  postExpedientEvent(docId: any, body: any, sharedagenda: string, serialNumber: any, applicationID: any) {
    const geturl = environment.apiURL + 'calendar/' + ((sharedagenda != '') ? sharedagenda : 'CreateEventExpediente') + '/event';
    let params = new HttpParams();
    let options;

    params = params.set("DocId", docId);
    params = params.set("SerialNumber", serialNumber);
    params = params.set("applicationID", applicationID);

    switch (this.loggeduser.Profile) {
      case 'MDGPR':
        if (body.CalendarName == 'Pessoal') {
          options = {
            headers: this.headersMdPessoal,
            params: params
          };
        }
        else if (body.CalendarName == 'Oficial') {
          options = {
            headers: this.headersMdOficial,
            params: params
          };
        }
        break;
      case 'PR':
        if (body.CalendarName == 'Pessoal') {
          options = {
            headers: this.headersPrPessoal,
            params: params
          };
        }
        else if (body.CalendarName == 'Oficial') {
          options = {
            headers: this.headersPrOficial,
            params: params
          };
        }
        break;
    }
    return this.http.post<any>(`${geturl}`, body, options)
  }
  createTaskEvent(folderId: any, body: any, sharedagenda: string, serialNumber: any, applicationID: any) {
    const geturl = environment.apiURL + 'calendar/' + ((sharedagenda != '') ? sharedagenda : 'CreateEventExpediente') + '/dispatch';
    let params = new HttpParams();
    let options;

    params = params.set("FolderId", folderId);
    params = params.set("SerialNumber", serialNumber);
    params = params.set("applicationID", applicationID);

    switch (this.loggeduser.Profile) {
      case 'MDGPR':
        if (body.CalendarName == 'Pessoal') {
          options = {
            headers: this.headersMdPessoal,
            params: params
          };
        }
        else if (body.CalendarName == 'Oficial') {
          options = {
            headers: this.headersMdOficial,
            params: params
          };
        }
        break;
      case 'PR':
        if (body.CalendarName == 'Pessoal') {
          options = {
            headers: this.headersPrPessoal,
            params: params
          };
        }
        else if (body.CalendarName == 'Oficial') {
          options = {
            headers: this.headersPrOficial,
            params: params
          };
        }
        break;
    }
    return this.http.post<any>(`${geturl}`, body, options)
  }

  postEventToApproveEdit(body: EventToApproveEdit) {
    const geturl = environment.apiURL + 'Tasks/EditEventTask';

    let options = {
      headers: this.headers,
    };

    return this.http.post<any>(`${geturl}`, body, options)
  }
}
