import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {environment} from '@environments/environment';
import {Observable} from "rxjs";

@Injectable({providedIn: 'root'})
export class ObjectsService {
  constructor(private http: HttpClient) {
  }

  listTypes(params?: {}): Observable<any> {
    return this.http.get<any>(`${environment.apiUrl}/api/object-types`, {params: params});
  }

  listObjects(params?: {}): Observable<any> {
    return this.http.get<any>(`${environment.apiUrl}/api/objects`, {params: params});
  }

  filters(type: string): Observable<any>  {
    return this.http.get<any>(`${environment.apiUrl}/api/${type}/filters`, {});
  }

  fetchType(id: string, params?: {}): Observable<any> {
    return this.http.get<any>(`${environment.apiUrl}/api/object-types/${id}`, {params: params});
  }

  fetchObject(id: string, params?: {}): Observable<any> {
    return this.http.get<any>(`${environment.apiUrl}/api/objects/${id}`, {params: params});
  }

  fetchModelForm(type: string, id?: string, params?: {}): Observable<any> {
    let url = `${environment.apiUrl}/api/forms/${type}` + (id ? `/${id}` : '');
    return this.http.get<any>(url, {params: params});
  }

  fetchModelFilters(type: string, params?: {}): Observable<any> {
    return this.http.get(`${environment.apiUrl}/api/filters/${type}`, {params: params});
  }


  documents(object: any) {
    let result = <any>[];
    this.fields(object, 'document').forEach(field => {
      field.value?.data.forEach(value => {
        result.push({name: field.multiple ? value.name : field.title, link: value.links?.open});
      });
    });
    return result;
  }
  fields(object: any, type?: string) {
    let result = [];
    object?.groups?.data.forEach(group => {
      group.fields?.data.forEach(field => {
        if (!type || (field.type === type)) result.push(field);
      });
    });
    return result;
  }

  getValue(object: any, fieldName: string) {
    let result = null;
    object?.groups?.data.forEach(group => {
      group.fields?.data.forEach(field => {
        if (field.name === fieldName) result = this.fieldValue(field);
      });
    });
    return result;
  }

  parsedFields(object: any, type?: string) {
    let result = [];
    this.fields(object, type).forEach(field => {
      field.value = this.fieldValue(field);
      result.push(field);
    });
    return result;
  }
  fieldValue(field) {
    let result = field.value?.data || field.value;
    if (!field.multiple && Array.isArray(result)) result = result[0];
    return result;
  }


  save(target: any, data: any): Observable<any> {
    if (target.objectId) return this.update(target.objectId, data);
    else if (target.objectTypeName) return this.store(target.objectTypeName, data);
    else if (target.modelTypeName && target.modelId) return this.updateModel(target.modelTypeName, target.modelId, data);
    else return this.storeModel(target.modelTypeName, data);
  }


  store(type: string, data: any): Observable<any> {
    return this.http.post(`${environment.apiUrl}/api/objects`, {type: type, properties: data});
  }

  update(id: string, data: any): Observable<any> {
    return this.http.put(`${environment.apiUrl}/api/objects/${id}`, data);
  }

  move(id: string, data: any): Observable<any> {
    return this.http.put(`${environment.apiUrl}/api/objects/move/${id}`, data);
  }

  destroy(id: string) {
    return this.http.delete(`${environment.apiUrl}/api/objects/${id}`);
  }


  storeModel(type: string, data: any): Observable<any> {
    return this.http.post(`${environment.apiUrl}/api/forms/${type}`, data);
  }

  updateModel(type: string, id: string, data: any): Observable<any> {
    return this.http.put(`${environment.apiUrl}/api/forms/${type}/${id}`, data);
  }

}
