import { ItemDataProvider } from '@dvn/core/components/views/dvn-app-view-detail-view-card/data-provider';
import { convertValues } from '@dvn/core/components/views/dvn-card-view/action-util';
import { generateFieldModelFromRawData } from '@dvn/core/doldurma/src/FieldModelGenerator';
import { SingleChoiceField } from '@dvn/core/doldurma/src/fields/single-choice';
import { InvalidationAction, NotificationAction } from '@dvn/core/models/actions';
import { ItemFetchState } from '@dvn/core/models/item-fetch-state';
import { findField } from '@dvn/core/util/field';
import { Component, Event, h, Host, Method, Prop, State } from '@stencil/core';
function getFieldFromFormFieldConfig(fields, fieldData) {
  return fieldData.field || findField(fields, fieldData.fieldId);
}
// sets value if the parameters contain value for fields
const prepareFields = (view, params = {}) => {
  const data = convertValues(view.conversionConfig, params);
  return view.ui.fields.map(formFieldConfig => {
    var _a;
    const field = generateFieldModelFromRawData(getFieldFromFormFieldConfig(view.table.fields, formFieldConfig));
    const value = data[field.id];
    if (value && field.type === SingleChoiceField.type) {
      const singleChoice = field;
      if (singleChoice.dataProvider) {
        // dvn-select doesn't show any data if it has a data provider (meaning that the options are not set)
        // we need to pass initial options with the selected value in it
        singleChoice.dataProvider.setInitialData([value]);
      }
      field.setValue(((_a = singleChoice.dataAdapter) === null || _a === void 0 ? void 0 : _a.value(value)) || value);
    }
    else {
      field.setValue(value);
    }
    return field;
  });
};
export class DvnAppViewFormView {
  constructor() {
    this.isProgressing = false;
    this.itemFetchState = ItemFetchState.init();
    this.onSubmit = (event) => {
      if (!this.view.handler.onSubmit) {
        return;
      }
      this.isProgressing = true;
      this.formErrors = undefined;
      this.view.handler.onSubmit(event).then(result => {
        this.isProgressing = false;
        if (result === null || result === void 0 ? void 0 : result.events) {
          result.events.forEach(eventToEmit => {
            if (eventToEmit instanceof InvalidationAction) {
              this.invalidation.emit(eventToEmit);
            }
            if (eventToEmit instanceof NotificationAction) {
              this.notification.emit(eventToEmit);
            }
          });
        }
        if (result === null || result === void 0 ? void 0 : result.navigation) {
          this.action.emit(result.navigation);
        }
      }).catch(errors => {
        this.isProgressing = false;
        this.formErrors = errors;
      });
    };
  }
  componentWillLoad() {
    var _a;
    const { apiData, params, view } = this;
    const { query, table } = view;
    if (query) {
      const queryParams = { itemId: params.itemId };
      // fetch the initial data if the query is provided
      this.itemDataProvider = new ItemDataProvider(apiData, queryParams, table, query, query.fields, (itemFetchState) => {
        this.itemFetchState = itemFetchState;
      });
      (_a = this.itemDataProvider) === null || _a === void 0 ? void 0 : _a.fetchData(this.itemFetchState);
    }
  }
  // needed for invalidation
  componentDidUpdate() {
    var _a;
    const { itemFetchState } = this;
    if (!itemFetchState.data && !itemFetchState.isPending && !itemFetchState.error) {
      (_a = this.itemDataProvider) === null || _a === void 0 ? void 0 : _a.fetchData(this.itemFetchState);
    }
  }
  async invalidate(_event) {
    var _a;
    (_a = this.itemDataProvider) === null || _a === void 0 ? void 0 : _a.fetchData(this.itemFetchState);
  }
  ;
  render() {
    const { view, params, formErrors, isProgressing } = this;
    const { i18n = {} } = view.ui;
    if (!view.query) {
      // show the form without any fetch related ui
      return (h(Host, null,
        h("h3", null, view.title),
        h("doldurma-form", { fields: prepareFields(view, params), onSubmit: this.onSubmit, submitButtonLabel: i18n.submit || 'Submit', progressing: isProgressing, formErrors: formErrors })));
    }
    const { itemFetchState } = this;
    return (h(Host, null,
      (!itemFetchState.isPending && !itemFetchState.error) &&
        h("h3", null, view.title),
      (!itemFetchState.isPending && !itemFetchState.error) &&
        h("doldurma-form", { fields: prepareFields(view, Object.assign(Object.assign({}, (params)), { item: itemFetchState.data })), onSubmit: this.onSubmit, submitButtonLabel: i18n.submit || 'Submit', progressing: isProgressing, formErrors: formErrors }),
      itemFetchState.isPending &&
        h("div", { class: "d-flex flex-grow-1 align-items-center justify-content-center detail-view-progress-container" },
          h("dvn-progress", { indefinite: true, tint: "primary" })),
      itemFetchState.error &&
        h("div", { class: "d-flex flex-grow-1 align-items-center justify-content-center flex-column detail-view-progress-container" },
          i18n.fetchError || 'Fetching data failed.',
          h("dvn-button", { onClick: () => { var _a; return (_a = this.itemDataProvider) === null || _a === void 0 ? void 0 : _a.fetchData(this.itemFetchState); } }, i18n.retry))));
  }
  static get is() { return "dvn-app-view-form-view"; }
  static get encapsulation() { return "scoped"; }
  static get originalStyleUrls() { return {
    "$": ["dvn-app-view-form-view.scss"]
  }; }
  static get styleUrls() { return {
    "$": ["dvn-app-view-form-view.css"]
  }; }
  static get properties() { return {
    "apiData": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "DataApi",
        "resolved": "DataApi",
        "references": {
          "DataApi": {
            "location": "import",
            "path": "@dvn/core/api"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "view": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "FormViewConfig",
        "resolved": "FormViewConfig",
        "references": {
          "FormViewConfig": {
            "location": "import",
            "path": "@dvn/core/models/form-view-config"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "params": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "FormViewParams",
        "resolved": "FormViewParams",
        "references": {
          "FormViewParams": {
            "location": "import",
            "path": "@dvn/core/components/views/dvn-app-view-form-view/params"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    }
  }; }
  static get states() { return {
    "isProgressing": {},
    "formErrors": {},
    "itemFetchState": {}
  }; }
  static get events() { return [{
      "method": "action",
      "name": "action",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "any",
        "resolved": "any",
        "references": {}
      }
    }, {
      "method": "invalidation",
      "name": "invalidation",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "any",
        "resolved": "any",
        "references": {}
      }
    }, {
      "method": "notification",
      "name": "notification",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "any",
        "resolved": "any",
        "references": {}
      }
    }]; }
  static get methods() { return {
    "invalidate": {
      "complexType": {
        "signature": "(_event: CustomEvent<InvalidationAction>) => Promise<void>",
        "parameters": [{
            "tags": [],
            "text": ""
          }],
        "references": {
          "Promise": {
            "location": "global"
          },
          "CustomEvent": {
            "location": "global"
          },
          "InvalidationAction": {
            "location": "import",
            "path": "@dvn/core/models/actions"
          }
        },
        "return": "Promise<void>"
      },
      "docs": {
        "text": "",
        "tags": []
      }
    }
  }; }
}
