import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { StringUtils } from '../../utilities/string-utils';

// @Injectable({
//   providedIn: 'root'
// })
//@Injectable()
export interface ICrudService<T> {
  getAll(): Observable<T[]>
  getById(id: any): Observable<T>;
  update(data: T): Observable<boolean>;
  createOrUpdate(data: T): Observable<T>;
  createOrUpdateAll(data: T[]): Observable<T[]>;
  delete(id: any): Observable<T>;
}


export class CrudService<T> implements ICrudService<T> {

  protected apiUrlFunc: (id?: string) => string = () => '';
  private GET_URL_GET_ALL = () => `${this.apiUrlFunc()}/GetAll?`;
  private GET_URL_GET_BY_ID = (id) => `${this.apiUrlFunc()}/GetById?id=${id}`;
  private POST_URL_UPDATE = () => `${this.apiUrlFunc()}/Update`
  private POST_URL_CREATE_OR_UPDATE = () => `${this.apiUrlFunc()}/CreateOrUpdate`
  private POST_URL_CREATE_OR_UPDATE_ALL = () => `${this.apiUrlFunc()}/CreateOrUpdateAll`
  private DELETE_URL_DELETE = (id) => `${this.apiUrlFunc()}/Delete?id=${id}`;

  constructor(protected http: HttpClient, apiUrlFunc: (id?: string) => string) {
    this.apiUrlFunc = apiUrlFunc;
  }


  getAll() {
    return this.http.get<T[]>(this.GET_URL_GET_ALL());
  }

  getById(id: string) {
    return this.http.get<T>(this.GET_URL_GET_BY_ID(id));
  }

  update(data: T) {
    return this.http.post<boolean>(this.POST_URL_UPDATE(),
      JSON.stringify(data), {
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
    });

  }
  createOrUpdate(data: T) {
    return this.http.post<T>(this.POST_URL_CREATE_OR_UPDATE(),
      JSON.stringify(data), {
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
    });

  }
  createOrUpdateAll(data: T[]) {
    return this.http.post<T[]>(this.POST_URL_CREATE_OR_UPDATE_ALL(),
      JSON.stringify(data), {
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
    });

  }
  delete(id: string) {
    return this.http.delete<T>(this.DELETE_URL_DELETE(id));
  }

  private post(url: string, obj: any) {
    return this.http.post<boolean>(url, JSON.stringify(obj),
      {
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        }
      }
    );
  }
  private put(url: string, obj: any) {
    return this.http.put<boolean>(url, JSON.stringify(obj),
      {
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        }
      }
    );
  }
}


@Injectable({
  providedIn: 'root'
})
export class CombinedKeyCrudService<T> implements ICrudService<T> {

  protected apiUrlFunc: (id?: string) => string = () => '';
  private GET_URL_GET_ALL = () => `${this.apiUrlFunc()}/GetAll?`;
  private POST_URL_UPDATE = () => `${this.apiUrlFunc()}/Update`
  private POST_URL_CREATE_OR_UPDATE = () => `${this.apiUrlFunc()}/CreateOrUpdate`
  private POST_URL_CREATE_OR_UPDATE_ALL = () => `${this.apiUrlFunc()}/CreateOrUpdateAll`
  private GET_URL_GET_BY_ID = (ids: string[]) => `${this.apiUrlFunc()}/GetById?${StringUtils.arrayToUrlParams('ids', ids)}`;
  private DELETE_URL_DELETE = (ids: string[]) => `${this.apiUrlFunc()}/Delete?${StringUtils.arrayToUrlParams('ids', ids)}`;
  constructor(
    protected http: HttpClient, apiUrlFunc: (id?: string) => string) {
    this.apiUrlFunc = apiUrlFunc;
  }

  getAll() {
    return this.http.get<T[]>(this.GET_URL_GET_ALL());
  }

  getById(ids: string[]) {
    return this.http.get<T>(this.GET_URL_GET_BY_ID(ids));
  }

  update(data: T) {
    return this.http.post<boolean>(this.POST_URL_UPDATE(),
      JSON.stringify(data), {
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
    });

  }
  createOrUpdate(data: T) {
    return this.http.post<T>(this.POST_URL_CREATE_OR_UPDATE(),
      JSON.stringify(data), {
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
    });

  }
  createOrUpdateAll(data: T[]) {
    return this.http.post<T[]>(this.POST_URL_CREATE_OR_UPDATE_ALL(),
      JSON.stringify(data), {
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
    });

  }
  delete(ids: string[]) {
    return this.http.delete<T>(this.DELETE_URL_DELETE(ids));
  }

  private post(url: string, obj: any) {
    return this.http.post<boolean>(url, JSON.stringify(obj),
      {
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        }
      }
    );
  }
  private put(url: string, obj: any) {
    return this.http.put<boolean>(url, JSON.stringify(obj),
      {
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        }
      }
    );
  }

} 
