import { Component, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, ElementRef, ViewEncapsulation } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { tap, take, map, catchError, switchMap, filter, shareReplay, retry } from 'rxjs/operators';
import { of, BehaviorSubject, Subject, combineLatest, zip } from 'rxjs';
import { State } from '@progress/kendo-data-query';
import { PipeContractService, Detail, Item, RequiredData, RateSchedule, Zone, Meter } from './pipe-contract.service';
import { MessageService } from '../_shared/services/message.service';
import { Validators } from '@angular/forms';
import { DialogService, DialogSettings } from '@progress/kendo-angular-dialog';
import { NotifyService } from '../_shared/services/notify.service';
import { TooltipDirective } from '@progress/kendo-angular-tooltip';
import { SelectableSettings } from '@progress/kendo-angular-grid';
import * as util from '../_shared/utils/util';
import { SuccessEvent, ErrorEvent, UploadComponent, UploadProgressEvent } from '@progress/kendo-angular-upload';
import { CustomFormBuilder } from '../_shared/services/custom-form-builder.service';
import { FAST_KENDO_COMMON, FAST_PAGE_COMMON } from '../app.config';

@Component({
  selector: 'app-pipe-contract',
  templateUrl: './pipe-contract.component.html',
  styleUrls: ['./pipe-contract.component.scss'],
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [FAST_PAGE_COMMON, FAST_KENDO_COMMON

  ]
})
export class PipeContractComponent {
  @ViewChild("grid", { read: ElementRef }) kendoGridEl: ElementRef;
  @ViewChild('tooltipGrid') tooltipGrid: TooltipDirective;
  @ViewChild('docUploadTarget') docUploadElem: UploadComponent;

  util = util;
  icons = util.icons;
  hasModifyPermission = false;
  detailForm = this.getDetailForm();
  detailInitialValues: Detail = this.detailForm.value as Detail;
  localRequiredData: RequiredData;
  gridScrollPosition: util.GridScrollPosition = { topPos: 0, leftPos: 0 };
  mySelection: number[] = [];
  manualChangesTriggering: boolean = false;
  docSaveUrl = `${window.location.origin}/api/PipeContract/UploadDoc`;

  gridLoading$ = new BehaviorSubject<boolean>(true)
  exporting$ = new BehaviorSubject<boolean>(false)
  detailLoading$ = new BehaviorSubject<boolean>(true);
  detailOpened$ = new BehaviorSubject<boolean>(false)
  refreshItems$ = new BehaviorSubject<string>(null)
  refreshDetail$ = new BehaviorSubject<number>(null)
  refreshPipeForProduct$ = new BehaviorSubject(null)
  refreshRequiredData$ = new BehaviorSubject(util.RefreshType.WithOthers)
  save$ = new Subject<util.SaveType>()
  delete$ = new Subject()
  exportClicked$ = new Subject()
  downloadDoc$ = new Subject<util.DocItem>()

  selectableSettings: SelectableSettings = {
    checkboxOnly: false,
    mode: 'single',
    enabled: true
  }

  state: State = {
    filter: null,
    group: null,
    skip: 0,
    sort: [{ field: 'ContractNum', dir: 'asc' }],
    take: 100
  };

  constructor(private messageService: MessageService, private titleService: Title, private service: PipeContractService, private fb: CustomFormBuilder, private ref: ChangeDetectorRef, private dialogService: DialogService, private notify: NotifyService) {

  }

  getDetailForm() {
    const fb = this.fb;
    const fg: util.FormModel<Detail> = fb.group({
      id: fb.ctr(0, Validators.required),
      contractNum: fb.ctr(null, Validators.required),
      startDate: fb.ctr(util.currentDate.toDate(), Validators.required),
      endDate: fb.ctr(null),
      isDefaultContract: fb.ctr(false, Validators.required),
      pipelineId: fb.ctr(null, Validators.required),
      contractTypeId: fb.ctr(1, Validators.required),
      rateScheduleId: fb.ctr(null),
      shipperId: fb.ctr(null, Validators.required),
      contractOwnerId: fb.ctr(null, Validators.required),
      capacityIsRelease: fb.ctr(false, Validators.required),
      capacityIsBuy: fb.ctr(true, Validators.required),
      capacityCounterpartyId: fb.ctr(null),
      capacityDemandCharge: fb.ctr(null),
      capacityRateUnitId: fb.ctr(1, Validators.required),
      receiptZoneIds: fb.ctr([]),
      receiptMeterIds: fb.ctr([]),
      deliveryZoneIds: fb.ctr([]),
      deliveryMeterIds: fb.ctr([]),
      isPtrContract: fb.ctr(false, Validators.required),
      isDefaultPtrContract: fb.ctr(false, Validators.required),
      documents: fb.ctr([]),
      notes: fb.ctr(null),
      productId: fb.ctr(null, Validators.required),
    });

    return fg
  }

  //this updates localDetailLoading whenever detailLoading$ changes so that we can check the loading status in this class
  localDetailLoading = true;
  detailLoadingWatcher$ = this.detailLoading$.pipe(
    tap(isLoading => {
      this.localDetailLoading = isLoading;
    }),
    shareReplay(1)
  )

  title$ = of('Pipeline Contract').pipe(
    tap((title) => util.trySetTitle(this.titleService, title))
  )

  requiredData$ = this.refreshRequiredData$.pipe(
    tap(() => this.detailLoading$.next(true)),
    switchMap(refreshType => {
      return combineLatest([this.service.requiredData$, of(refreshType)]);
    }),
    map(([requiredData, refreshType]) => {
      this.localRequiredData = requiredData;
      if (refreshType === util.RefreshType.SelfOnly)
        this.detailLoading$.next(false);
      return requiredData;
    }),
    tap((requiredData) => {
      this.hasModifyPermission = requiredData.hasModifyPermission;
      util.focusInputTarget()
    }),
    shareReplay(1),
    catchError(err => {
      return util.handleError(err, this.messageService)
    }), retry(10)
  )

  items$ = this.refreshItems$.pipe(
    tap(() => {
      this.gridLoading$.next(true);
    }),
    switchMap(() => {
      return this.service.getItems(this.state);
    }),
    tap(() => {
      this.gridLoading$.next(false);
      util.goToSavedGridScrollPos(this.kendoGridEl, this.gridScrollPosition);
    }),
    shareReplay(1),
    catchError(err => {
      return util.handleError(err, this.messageService)
    }), retry(10)
  )

  exportAction$ = this.exportClicked$.pipe(
    switchMap(() => {
      this.exporting$.next(true);
      return this.service.exportItems(this.state, 'Pipeline Contract.xlsx');
    }),
    tap(res => {
      util.openOrSaveFile(res.fileBlob, res.fileName);
      this.exporting$.next(false);
    }),
    shareReplay(1),
    catchError(err => {
      this.exporting$.next(false);
      return util.handleError(err, this.messageService)
    }), retry(10)
  )

  detail$ = this.refreshDetail$.pipe(
    filter(id => id !== null),
    switchMap(id => {
      this.detailLoading$.next(true);
      this.detailForm.disable();
      this.detailForm.reset();
      if (id === 0)
        return of(this.detailInitialValues);
      else
        return this.service.getDetail(id);
    }),
    map(result => {
      const detail: Detail = result;
      if (detail) {
        util.convertToDates(detail);
        this.detailForm.setValue(detail);
      }
      return detail;
    }),
    tap(() => {
      this.detailFinishedLoading();
      this.refreshPipeForProduct$.next(null);
    }),
    shareReplay(1),
    catchError(err => {
      this.closeDetail(false);
      return util.handleError(err, this.messageService)
    }), retry(10)
  )

  saveResult$ = this.save$.pipe(
    switchMap(saveType => {
      this.detailLoading$.next(true);
      this.detailForm.disable();
      const itemToSave: Detail = this.detailForm.value as Detail;
      return this.service.saveDetail(itemToSave, saveType);
    }),
    tap((saveResult) => {
      this.notify.success('save successful');
      this.closeDetail(false);
      this.refreshItems$.next(null);
      this.mySelection = [saveResult];
    }),
    shareReplay(1),
    catchError(err => {
      this.detailFinishedLoading();
      return util.handleError(err, this.messageService)
    }), retry(10)
  )

  deleteResult$ = this.delete$.pipe(
    switchMap(() => {
      this.detailLoading$.next(true);
      this.detailForm.disable();
      const itemToDelete: Detail = this.detailForm.getRawValue();
      return this.service.deleteDetail(itemToDelete.id);
    }),
    tap(() => {
      this.notify.success('delete successful');
      this.detailFinishedLoading();
      this.closeDetail(false);
      this.refreshItems$.next(null);
    }),
    shareReplay(1),
    catchError(err => {
      this.detailLoading$.next(false);
      this.detailForm.enable();
      return util.handleError(err, this.messageService)
    }), retry(10)
  )

  isCapacityReleaseChanged$ = this.detailForm.get('capacityIsRelease').valueChanges.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    tap(() => {
      this.updateFormControlStates();
    }),
    shareReplay(1),
    catchError(err => {
      return util.handleError(err, this.messageService)
    }), retry(1)
  )

  productChanged$ = this.detailForm.get('productId').valueChanges.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    tap(() => {
      this.refreshPipeForProduct$.next(null);
      this.refreshRateSchedules$.next(null);
      this.refreshReceiptZones$.next(null);
      this.refreshDeliveryZones$.next(null);
    }),
    shareReplay(1),
  )

  pipelineChanged$ = this.detailForm.get('pipelineId').valueChanges.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    tap(() => {
      this.refreshRateSchedules$.next(null);
      this.refreshReceiptZones$.next(null);
      this.refreshDeliveryZones$.next(null);
    }),
    shareReplay(1),
  )

  contractTypeChanged$ = this.detailForm.get('contractTypeId').valueChanges.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    tap(() => {
      this.refreshRateSchedules$.next(null);
    }),
    shareReplay(1)
  )

  getSelectedIdsWithAllItemCorrection(selectedIds: number[]): number[] {
    if (selectedIds && selectedIds.length > 0) {
      const allItemSelected = selectedIds[selectedIds.length - 1] === 0;
      if (allItemSelected)
        selectedIds = selectedIds = [0]; //removes any items that are not ALL
      else
        selectedIds = selectedIds.filter(x => x > 0); //removes the ALL item
    }
    return selectedIds
  }

  receiptZonesChanged$ = this.detailForm.get('receiptZoneIds').valueChanges.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    tap((selectedIds: number[]) => {
      selectedIds = this.getSelectedIdsWithAllItemCorrection(selectedIds);
      this.detailForm.patchValue({ receiptZoneIds: selectedIds }, { emitEvent: false });
      this.refreshReceiptMeters$.next(null);
    }),
    shareReplay(1)
  )

  deliveryZonesChanged$ = this.detailForm.get('deliveryZoneIds').valueChanges.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    tap((selectedIds: number[]) => {
      selectedIds = this.getSelectedIdsWithAllItemCorrection(selectedIds);
      this.detailForm.patchValue({ deliveryZoneIds: selectedIds }, { emitEvent: false });
      this.refreshDeliveryMeters$.next(null);
    }),
    shareReplay(1)
  )

  receiptMetersChanged$ = this.detailForm.get('receiptMeterIds').valueChanges.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    tap((selectedIds: number[]) => {
      selectedIds = this.getSelectedIdsWithAllItemCorrection(selectedIds);
      this.detailForm.patchValue({ receiptMeterIds: selectedIds }, { emitEvent: false });
    }),
    shareReplay(1)
  )

  deliveryMetersChanged$ = this.detailForm.get('deliveryMeterIds').valueChanges.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    tap((selectedIds: number[]) => {
      selectedIds = this.getSelectedIdsWithAllItemCorrection(selectedIds);
      this.detailForm.patchValue({ deliveryMeterIds: selectedIds }, { emitEvent: false });
    }),
    shareReplay(1)
  )

  subPipeForProduct$ = this.refreshPipeForProduct$.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    map(() => {
      const productId = this.detailForm.get('productId').value;
      // const isProductGas = this.detailForm.get('productId').value === util.Product.NaturalGas;
      // const isProductCrude = this.detailForm.get('productId').value === util.Product.CrudeOil;
      const currentPipeId = this.detailForm.get('pipelineId').value;
      // const isSelectedPipeCrude = this.localRequiredData.pipelines.some(p => p.pipeId === currentPipeId);
      // const isSelectedPipeGas = this.localRequiredData.pipelines.some(p => p.pipeId === currentPipeId);
      const selectedPipeMathesProduct = this.localRequiredData.pipelines.some(p => p.pipeId === currentPipeId && p.productIds.includes(productId));
      const pipes = this.localRequiredData.pipelines;

      if (!productId)
        return pipes;

      if (!selectedPipeMathesProduct)
        this.detailForm.patchValue({ pipelineId: null }, { emitEvent: false });

      const filteredPipes = pipes.filter(p => p.productIds.includes(productId));
      return filteredPipes;
    }),
    shareReplay(1),
    catchError(err => {
      return util.handleError(err, this.messageService)
    }), retry(10)
  )

  refreshRateSchedules$ = new Subject<string>()
  rateSchedulesForPipeContractType$ = this.refreshRateSchedules$.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    map(() => {
      const pipelineId: number = this.detailForm.get('pipelineId').value;
      const contractTypeId = this.detailForm.get('contractTypeId').value;
      const productId = this.detailForm.get('productId').value;
      let subRateSchedules: RateSchedule[] = [];

      if (pipelineId) {
        subRateSchedules = this.localRequiredData.rateSchedules.filter(rateSchedule => {
          const hasContractTypeId = contractTypeId !== null;
          const isMappedItem = rateSchedule.pipelineId === pipelineId && (!hasContractTypeId || rateSchedule.contractType === contractTypeId);
          if (isMappedItem && rateSchedule.productId !== null) {
            const mappedProductCatItem = rateSchedule.productId === productId;
            return mappedProductCatItem;
          }
          else
            return isMappedItem;
        });
      }

      const rateScheduleId = this.detailForm.get('rateScheduleId').value;
      if (subRateSchedules && subRateSchedules.findIndex(x => x.id === rateScheduleId) === -1)
        this.detailForm.patchValue({ rateScheduleId: null }, { emitEvent: false });

      if (!this.localDetailLoading && subRateSchedules && subRateSchedules.length === 1)
        this.detailForm.patchValue({ rateScheduleId: subRateSchedules[0].id }, { emitEvent: false });

      return subRateSchedules;
    }),
    shareReplay(1)
  )

  refreshReceiptZones$ = new Subject<string>()
  receiptZonesForPipe$ = this.refreshReceiptZones$.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    map(() => {
      const pipelineId: number = this.detailForm.get('pipelineId').value;
      let subZones: Zone[] = [];

      if (pipelineId) {
        subZones = this.localRequiredData.zones.filter(zone => {
          return zone.pipelineId === pipelineId || zone.pipelineId === 0;
        });
      }

      let receiptZoneIds: number[] = this.detailForm.get('receiptZoneIds').value;
      if (subZones && subZones.length && receiptZoneIds && receiptZoneIds.length > 0) {
        receiptZoneIds = receiptZoneIds.filter(receiptZoneId => {
          return subZones.findIndex(x => x.id === receiptZoneId) !== -1;
        });
      } else
        receiptZoneIds = [];

      this.detailForm.patchValue({ receiptZoneIds: receiptZoneIds }, { emitEvent: false });

      if (!this.localDetailLoading && subZones && subZones.length === 1)
        this.detailForm.patchValue({ receiptZoneIds: [subZones[0].id] }, { emitEvent: false });

      return subZones;
    }),
    tap(() => {
      this.refreshReceiptMeters$.next(null);
    }),
    shareReplay(1)
  )

  refreshDeliveryZones$ = new Subject<string>()
  deliveryZonesForPipe$ = this.refreshDeliveryZones$.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    map(() => {
      const pipelineId: number = this.detailForm.get('pipelineId').value;
      let subZones: Zone[] = [];

      if (pipelineId) {
        subZones = this.localRequiredData.zones.filter(zone => {
          return zone.pipelineId === pipelineId || zone.pipelineId === 0;
        });
      }

      let deliveryZoneIds: number[] = this.detailForm.get('deliveryZoneIds').value;
      if (subZones && subZones.length && deliveryZoneIds && deliveryZoneIds.length > 0) {
        deliveryZoneIds = deliveryZoneIds.filter(deliveryZoneId => {
          return subZones.findIndex(x => x.id === deliveryZoneId) !== -1;
        });
      } else
        deliveryZoneIds = [];

      this.detailForm.patchValue({ deliveryZoneIds: deliveryZoneIds }, { emitEvent: false });

      if (!this.localDetailLoading && subZones && subZones.length === 1)
        this.detailForm.patchValue({ deliveryZoneIds: [subZones[0].id] }, { emitEvent: false });

      return subZones;
    }),
    tap(() => {
      this.refreshDeliveryMeters$.next(null);
    }),
    shareReplay(1)
  )

  refreshReceiptMeters$ = new Subject<string>()
  metersForReceiptZones$ = this.refreshReceiptMeters$.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    map(() => {
      const pipelineId: number = this.detailForm.get('pipelineId').value;
      const receiptZoneIds: number[] = this.detailForm.get('receiptZoneIds').value;
      const isAllZones: boolean = receiptZoneIds && receiptZoneIds.length > 0 && receiptZoneIds.findIndex(zoneId => zoneId === 0) !== -1;
      let metersForPipe: Meter[] = [];
      let receiptMeters: Meter[] = [];

      if (pipelineId) {
        metersForPipe = this.localRequiredData.meters.filter(meter => meter.pipeId === pipelineId);
      }
      if (isAllZones) {
        receiptMeters = metersForPipe;
      }
      if (!isAllZones && receiptZoneIds && receiptZoneIds.length > 0) {
        receiptMeters = metersForPipe.filter(meter => {
          return receiptZoneIds.findIndex(zoneId => zoneId === meter.zoneId) !== -1;
        });
      }
      if (receiptMeters.length === 1) {
        this.detailForm.get('receiptMeterIds').setValue([receiptMeters[0].meterId]);
      }
      if (receiptMeters.length === 0) {
        this.detailForm.get('receiptMeterIds').setValue([]);
      }
      return receiptMeters;
    }),
    shareReplay(1)
  )

  refreshDeliveryMeters$ = new Subject<string>()
  metersForDeliveryZones$ = this.refreshDeliveryMeters$.pipe(
    filter(() => !this.localDetailLoading || this.manualChangesTriggering),
    map(() => {
      const pipelineId: number = this.detailForm.get('pipelineId').value;
      const deliveryZoneIds: number[] = this.detailForm.get('deliveryZoneIds').value;
      const isAllZones: boolean = deliveryZoneIds && deliveryZoneIds.length > 0 && deliveryZoneIds.findIndex(zoneId => zoneId === 0) !== -1;
      let metersForPipe: Meter[] = [];
      let deliveryMeters: Meter[] = [];

      if (pipelineId) {
        metersForPipe = this.localRequiredData.meters.filter(meter => meter.pipeId === pipelineId);
      }
      if (isAllZones) {
        deliveryMeters = metersForPipe;
      }
      if (!isAllZones && deliveryZoneIds && deliveryZoneIds.length > 0) {
        deliveryMeters = metersForPipe.filter(meter => deliveryZoneIds.findIndex(zoneId => zoneId === meter.zoneId) !== -1);
      }
      if (deliveryMeters.length === 1) {
        this.detailForm.get('deliveryMeterIds').setValue([deliveryMeters[0].meterId]);
      }
      if (deliveryMeters.length === 0) {
        this.detailForm.get('deliveryMeterIds').setValue([]);
      }
      return deliveryMeters;
    }),
    shareReplay(1)
  )

  manualTriggersCompleting$ = zip(
    this.rateSchedulesForPipeContractType$,
    this.receiptZonesForPipe$,
    this.deliveryZonesForPipe$,
    this.metersForReceiptZones$,
    this.metersForDeliveryZones$,
    this.subPipeForProduct$
  ).pipe(
    filter(() => this.manualChangesTriggering),
    tap(() => {
      this.manualChangesTriggering = false;
      this.detailForm.enable();
      this.updateFormControlStates();
      this.detailLoading$.next(false);
      util.focusInputTarget();
    })
  )

  downloadDocResult$ = this.downloadDoc$.pipe(
    filter(docItem => {
      return docItem && docItem.fileNameOnDisk !== null;
    }),
    switchMap(fileNamePair => {
      return this.service.downloadDoc(fileNamePair.fileNameOriginal, fileNamePair.fileNameOnDisk);
    }),
    tap(res => {
      util.openOrSaveFile(res.fileBlob, res.fileName);
    }),
    catchError(err => {
      return util.handleError(err, this.messageService);
    }), retry(10)
  )

  openDetail(id: number): void {
    this.tooltipGrid.hide();
    util.saveGridScrollPos(this.kendoGridEl, this.gridScrollPosition);
    this.refreshDetail$.next(id);
    this.detailOpened$.next(true);
  }

  onDetailClosing() {
    util.onDetailChanging(this.detailForm, this.dialogService, this.closeDetail, this.save, { extraActionParamValue: true });
  }

  closeDetail = (isFromInterface: boolean) => {
    this.detailOpened$.next(false);

    if (isFromInterface)
      util.goToSavedGridScrollPos(this.kendoGridEl, this.gridScrollPosition);
  }

  detailFinishedLoading(): void {
    this.manualChangesTriggering = true;
    this.refreshRateSchedules$.next(null);
    this.refreshReceiptZones$.next(null);
    this.refreshDeliveryZones$.next(null);
  }

  add(): void {
    this.openDetail(0);
  }

  edit(dataItem: Item): void {
    this.openDetail(dataItem.Id);
  }

  save = (saveType: util.SaveType) => {
    this.detailForm.markAllAsTouched();
    if (this.detailForm.valid)
      this.save$.next(saveType);
    else
      this.notify.error("validation failed");
  }

  delete(): void {
    const deleteConfirmSettings: DialogSettings = {
      title: "Please confirm",
      content: "Are you sure you want to delete this item?",
      actions: [{ text: 'No' }, { text: 'Yes', cssClass: 'k-primary' }],
      cssClass: 'utilPrompt'
    }

    this.dialogService.open(deleteConfirmSettings).result.pipe(take(1)).subscribe(result => {
      if (util.getDialogAction(result) === util.dialogAction.Yes)
        this.delete$.next(null);
    });
  }

  export(): void {
    this.exportClicked$.next(null);
  }

  dataStateChange(state: State): void {
    this.gridScrollPosition = { topPos: 0, leftPos: 0 };
    util.fixKendoQueryFilter(state.filter);
    this.state = state;
    this.refreshItems$.next(null);
  }

  refreshDropdowns() {
    this.refreshRequiredData$.next(util.RefreshType.SelfOnly);
  }

  updateFormControlStates() {
    const isCapacityRelease: boolean = this.detailForm.get('capacityIsRelease').value;

    const controlCapacityIsBuy = this.detailForm.get('capacityIsBuy');
    const controlCapacityCounterpartyId = this.detailForm.get('capacityCounterpartyId');
    const controlCapacityDemandCharge = this.detailForm.get('capacityDemandCharge');
    const controlCapacityRateUnitId = this.detailForm.get('capacityRateUnitId');
    if (isCapacityRelease) {
      controlCapacityIsBuy.enable();
      controlCapacityCounterpartyId.enable();
      controlCapacityDemandCharge.enable();
      controlCapacityRateUnitId.enable();
    }
    else {
      controlCapacityIsBuy.disable();
      controlCapacityCounterpartyId.disable();
      controlCapacityDemandCharge.disable();
      controlCapacityRateUnitId.disable();
    }
  }

  docUploadSuccess(value: SuccessEvent) {
    const newdocitems: util.DocItem[] = value.response.body;
    let docs: util.DocItem[] = this.detailForm.get('documents').value;
    if (docs)
      docs = docs.concat(newdocitems);
    else
      docs = newdocitems;
    this.detailForm.patchValue({ documents: docs });
    this.detailForm.markAsDirty();
  }

  docComplete() {
    this.docUploadElem.clearFiles();
  }

  docUploadError(value: ErrorEvent) {
    util.handleError(value.response, this.messageService);
  }

  downloadDoc(doc: util.DocItem) {
    this.downloadDoc$.next(doc)
  }

  removeDoc(doc: util.DocItem) {
    const docs: util.DocItem[] = this.detailForm.get('documents').value;
    const indexToRemove = docs.findIndex(x => x.fileNameOnDisk === doc.fileNameOnDisk);
    docs.splice(indexToRemove, 1);
    this.detailForm.patchValue({ documents: docs });
    this.detailForm.markAsDirty();
  }

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  uploadProgress(event: UploadProgressEvent) {
    this.ref.detectChanges();
  }

  filterPipelines$ = new BehaviorSubject<string>(null)
  pipelines$ = this.filterPipelines$.pipe(util.filterSpecials(this.detailLoading$, this.subPipeForProduct$, null, 'pipeName'));

  filterContractTypes$ = new BehaviorSubject<string>(null)
  contractTypes$ = this.filterContractTypes$.pipe(util.filterIdNames(this.detailLoading$, this.requiredData$, 'contractTypes'));

  filterRateSchedules$ = new BehaviorSubject<string>(null)
  rateSchedules$ = this.filterRateSchedules$.pipe(util.filterSpecials(this.detailLoading$, this.rateSchedulesForPipeContractType$, null, 'name'));

  filterShippers$ = new BehaviorSubject<string>(null)
  shippers$ = this.filterShippers$.pipe(util.filterIdNames(this.detailLoading$, this.requiredData$, 'counterparties'));

  filterContractOwners$ = new BehaviorSubject<string>(null)
  contractOwners$ = this.filterContractOwners$.pipe(util.filterIdNames(this.detailLoading$, this.requiredData$, 'counterparties'));

  filterCapacityCounterparties$ = new BehaviorSubject<string>(null)
  capacityCounterparties$ = this.filterCapacityCounterparties$.pipe(util.filterIdNames(this.detailLoading$, this.requiredData$, 'counterparties'));

  filterRateUnits$ = new BehaviorSubject<string>(null)
  rateUnits$ = this.filterRateUnits$.pipe(util.filterIdNames(this.detailLoading$, this.requiredData$, 'rateUnits'));

  filterReceiptZones$ = new BehaviorSubject<string>(null)
  receiptZones$ = this.filterReceiptZones$.pipe(util.filterSpecials(this.detailLoading$, this.receiptZonesForPipe$, null, 'name'));

  filterDeliveryZones$ = new BehaviorSubject<string>(null)
  deliveryZones$ = this.filterDeliveryZones$.pipe(util.filterSpecials(this.detailLoading$, this.deliveryZonesForPipe$, null, 'name'));

  filterReceiptMeters$ = new BehaviorSubject<string>(null)
  receiptMeters$ = this.filterReceiptMeters$.pipe(util.filterSpecials(this.detailLoading$, this.metersForReceiptZones$, null, 'meterName'));

  filterDeliveryMeters$ = new BehaviorSubject<string>(null)
  deliveryMeters$ = this.filterDeliveryMeters$.pipe(util.filterSpecials(this.detailLoading$, this.metersForDeliveryZones$, null, 'meterName'));

  filterProducts$ = new BehaviorSubject<string>(null)
  products$ = this.filterProducts$.pipe(util.filterIdNames(this.detailLoading$, this.requiredData$, 'products'));
}
