import { CustomMultipleSelection } from './select2-adapters/custom-multiple-selection';
import { I18N } from 'aurelia-i18n';
import { TargetInstruction, bindingMode, TaskQueue, createOverrideContext, observable, BindingEngine, computedFrom, OverrideContext, Disposable } from 'aurelia-framework';
import { processContent } from 'aurelia-framework';
import { customElement, bindable } from "aurelia-templating";
import { GridDataSource } from "../../data/data-source";
import * as breeze from 'breeze-client';
import { CreateOtions } from "../../resources/attributes/select2-attribute";
import { UIInternal } from '../../utils/ui-internal';
import { BaseInput } from './base-input';
import { Options, Translation } from 'select2';
import { Datacontext } from '../../data/data-context';
import 'select2';
import { CustomAjaxAdapter, CustomSelectAdapter } from './select2-adapters/custom-ajax-adapter';
import { customAttachBody } from './select2-adapters/custom-attach-body';
import { CustomDropdownAdapter } from './select2-adapters/custom-dropdown-adapter';
import { EventAggregator, Subscription } from 'aurelia-event-aggregator';
import { CustomAllowClear } from './select2-adapters/custom-allow-clear';
import { Config } from '../../config';

@customElement('ui-select')
@processContent(makePartReplacementFromContent)
export class UISelect extends BaseInput {
  @bindable({ defaultBindingMode: bindingMode.twoWay }) public value: AnyObject;
  @bindable({ defaultBindingMode: bindingMode.twoWay }) public placeholder: string = "";
  @bindable({ defaultBindingMode: bindingMode.toView }) public dataSource: GridDataSource<breeze.Entity> = null;
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public optionsValue: string = "id";
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public optionsText: string;
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public createOptions: CreateOtions;
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public sortColumn: string;
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public filterProperties: string;
  @bindable({ defaultBindingMode: bindingMode.twoWay }) public itemTemplate: string;
  @bindable({ defaultBindingMode: bindingMode.twoWay }) public headerTemplate: string;
  @bindable({ defaultBindingMode: bindingMode.twoWay }) public footerTemplate: string;
  @bindable({ defaultBindingMode: bindingMode.toView }) allowClear: boolean = true;
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public pageSize: number = 25;
  @bindable({ defaultBindingMode: bindingMode.twoWay }) public dropdownCssClass: string;
  @bindable({ defaultBindingMode: bindingMode.toView }) public onChange: (args: { value?: any }) => void = () => { };
  @bindable({ defaultBindingMode: bindingMode.toView }) public onReady: () => void = () => { };
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public selectionTitle: string | boolean = true;
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public dropdownAutoWidth: boolean = false;
  @bindable({ defaultBindingMode: bindingMode.oneTime }) public focusSearchWhenOpen: boolean;

  @observable
  isFocus: boolean = false;
  private selectionTemplate: string;
  private parentContext: object;
  private $select: JQuery<Element>;
  private select2Instance: Select2.Select2;
  private callNumber: number = 0;
  public multiple: boolean;
  public tags: boolean;
  public ignoreChange = false;
  private onSelectedSize: string;
  private bindingContext: Object;
  private closeOnFooterClick: boolean = false;
  private closeOnHeaderClick: boolean = false;
  private clickableElements: Array<ChildNode> = [];
  private changeLanguageSubscription: Subscription;
  private onChangeCollectionObserverDisposables: Array<Disposable> = [];

  private submitOnLoad = {
    isLoading: false,
    isSubmitting: false
  };

  @computedFrom("isFocus")
  get isFocusClass(): string {
    if (this.disabled === false && this.isDisabled === false && this.readonly === false && this.isFocus === true) {
      return 'ui-select--focus';
    }
    return '';
  }

  @computedFrom("multiple")
  get isMultipleClass(): string {
    if (this.multiple === true) {
      return 'ui-select--multiple';
    }
    return '';
  }

  constructor(element: Element, targetInstruction: TargetInstruction, private datacontext: Datacontext, private i18n: I18N, private bindingEngine: BindingEngine, private taskQueue: TaskQueue, private eventAggregator: EventAggregator, private config: Config) {
    super(element);
    this.itemTemplate = this.getTemplate(targetInstruction, "itemTemplate");
    this.headerTemplate = this.getTemplate(targetInstruction, "headerTemplate");
    this.footerTemplate = this.getTemplate(targetInstruction, "footerTemplate");
    this.closeOnFooterClick = targetInstruction.elementInstruction["closeOnFooterClick"];
    this.closeOnHeaderClick = targetInstruction.elementInstruction["closeOnHeaderClick"];
    this.selectionTemplate = this.getTemplate(targetInstruction, "selectionTemplate");
    this.multiple = element.hasAttribute("multiple");
    this.tags = element.hasAttribute("tags");
    if (element.hasAttribute('on-selected-size')) {
      this.onSelectedSize = element.getAttribute('on-selected-size');
    }
  }

  public bind(bindingContext: Object, overrideContext?: any) {
    super.bind();
    this.bindingContext = bindingContext;
    this.parentContext = overrideContext;

    // Due to virtualization, the valueChange must be called when new rows are binded.
    if (hasParent(this.element, "ui-table")) {
      this.valueChanged(this.value, null);
    }
    this.focusSearchWhenOpen ??= this.config.globalConfig.uiSelectFocusSearchWhenOpen;
  }

  public attached() {
    UIInternal.queueMicroTask(() => {
      this.buildSelect2();
      this.setupSelect2EventsHandler();
      if (this.value != null && Object.keys(this.value).length > 0 && Object.keys(this.value).indexOf('id') > -1) {
        this.$select.val(this.value.id + "").trigger("change");
        //this.select.val(this.value).trigger("change");
      }
      else {
        this.$select.val(this.value).trigger("change");
      }


      if (Array.isArray(this.value)) {
        let observer = this.bindingEngine.collectionObserver(this.value);
        this.onChangeCollectionObserverDisposables.push(observer.subscribe(() => {
          this.$select?.val(this.value).trigger("change");
          this.callOnChangeCallback(this.value);
        }));
      }
      if (this.headerTemplate?.length > 0) {
        let $searchfield = this.select2Instance.$dropdown.find(".select2-search").first();
        const view = UIInternal.compileTemplate(this.headerTemplate, this, createOverrideContext(this.bindingContext, this.parentContext as OverrideContext));
        if (this.closeOnHeaderClick) {
          view.fragment.childNodes?.forEach(child => {
            child.addEventListener('click', this.closeOnClickHandler);
            this.clickableElements.push(child);
          });
        }
        $searchfield.after($(view.fragment));
      }
      if (this.footerTemplate?.length > 0) {
        let $searchresults = this.select2Instance.$dropdown.find(".select2-results").first();
        const view = UIInternal.compileTemplate(this.footerTemplate, this.bindingContext, createOverrideContext(this.bindingContext, this.parentContext as OverrideContext));
        if (this.closeOnFooterClick) {
          view.fragment.childNodes?.forEach(child => {
            child.addEventListener('click', this.closeOnClickHandler);
            this.clickableElements.push(child);
          });
        }
        $searchresults.after($(view.fragment));
      }
      var observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
          if (mutation.attributeName === "class") {
            var attributeValue = $(mutation.target).prop(mutation.attributeName) as string;
            if (attributeValue.indexOf('select2-container--open') > -1 || attributeValue.indexOf('select2-container--focus') > -1) {
              this.isFocus = true;
            }
            else {
              this.isFocus = false;
            }

          }
        });
      });
      observer.observe(this.select2Instance.$container.get(0), {
        attributes: true
      });

      if (this.value) {
        this.resizeSelection(true);
      }

      this.manageSelectionTitle();

      UIInternal.nextTick(() => this.onReady());
    });
    this.changeLanguageSubscription = this.eventAggregator.subscribe(UIInternal.EVT_CHANGE_LANGUAGE, () => {
      this.changeLanguage();
    });
  }

  public localEntityMatcher = (a, b) => {
    var a_id = a != null && a.id != null ? a.id : a;
    var b_id = b != null && b.id != null ? b.id : b;
    if (a_id == "") a_id = 0;
    if (b_id == "") b_id = 0;
    return (a_id != null && b_id != null && a_id.toString != null && b_id.toString != null) ? a_id.toString() === b_id.toString() : a_id == b_id;
  }

  setupSelect2EventsHandler() {
    let _this = this;
    let eventHandler = (e: any) => this.onKeyPressed(e);
    let getSearchField = () => document.getElementsByClassName('select2-search__field')[0];
    this.$select.on('select2:closing', function (e) {
      $(e.target).data("select2").$selection.one('focus focusin', function (e) {
        e.stopPropagation();
      });

      if (false == _this.multiple) {
        // Avoid closing when doing an ENTER and still loading
        if (_this.submitOnLoad.isLoading && _this.submitOnLoad.isSubmitting) {
          e.stopPropagation();
        } else {
          // When closing, remove event handler
          getSearchField()?.removeEventListener('keydown', eventHandler, true);
        }
      }
    });
    this.$select.on('select2:open', function (e) {
      if (e.currentTarget.tagName.toUpperCase() == 'SELECT') {
        if (_this.focusSearchWhenOpen) {
          $('.select2-search--dropdown input.select2-search__field').get(0)?.focus();
          $('.select2-search--dropdown input.select2-search__field').trigger('focus');
          setTimeout(() => {
            $('.select2-search--dropdown input.select2-search__field').get(0)?.focus();
            $('.select2-search--dropdown input.select2-search__field').trigger('focus');
          }, 0);
        } else {
          $('.select2-search--dropdown input.select2-search__field').get(0)?.blur();
          $('.select2-search--dropdown input.select2-search__field').trigger('blur');
          setTimeout(() => {
            $('.select2-search--dropdown input.select2-search__field').get(0)?.blur();
            $('.select2-search--dropdown input.select2-search__field').trigger('blur');
          }, 0);
        }

        if (false == _this.multiple) {
          // Add event handler on opening
          getSearchField()?.addEventListener('keydown', eventHandler, true);
        }
      }
    });
  }

  private onKeyPressed(event: KeyboardEvent) {
    if (this.multiple) {
      return true;
    } else if (event.key == 'Enter') {
      if (this.submitOnLoad.isLoading) {
        // ENTER during loading: stop default behaviour
        event.stopPropagation();
        event.preventDefault();
        this.submitOnLoad.isSubmitting = true;
        return false;
      }
    } else if (event.key.length == 1
      || ['Backspace', 'Clear', 'Delete', 'EraseEof', 'Insert', 'Paste', 'Undo', 'Redo'].indexOf(event.key) >= 0) {
      // content entered/removed, a search will be triggered 
      // set loading flag (needed because of debounce on ajax call)
      this.submitOnLoad.isLoading = true;
    }
    return true;
  }

  getTemplate(targetInstruction: any, templatePropertyName: string) {
    if (targetInstruction.elementInstruction[templatePropertyName] == null) return null;
    return "<template>" + <any>targetInstruction.elementInstruction[templatePropertyName] + "</template>";
  }

  getTemplateFromSelect2 = (select2Data) => {
    if (this.itemTemplate?.length > 0 && select2Data.data != null) {
      let view = UIInternal.compileTemplate(this.itemTemplate, this, select2Data.data);
      if (view.attached != null) view.attached();
      return view.fragment;
    }
    return select2Data.text;
  }

  getTemplateSelection = (select2Data) => {
    if (this.selectionTemplate?.length > 0) {
      const overrideContext = createOverrideContext(this.bindingContext, this.parentContext as OverrideContext);
      let view = UIInternal.compileTemplate(this.selectionTemplate, this, createOverrideContext(select2Data, overrideContext));
      if (view.attached != null) view.attached();
      return view.fragment.textContent.trim().length > 0 ? view.fragment : select2Data.text;
    }
    return select2Data.text;
  }

  private changeLanguage() {
    UIInternal.nextTick(() => this.buildSelect2());
  }

  private buildSelect2() {
    const options = this.fillOptions();
    this.$select = $(this.inputEl).select2(options);
    this.select2Instance = this.$select.data("select2");
  }

  private fillOptions() {
    let options: Options = {};

    options.placeholder = this.placeholder;
    let minimumInputLength = 0;
    if (this.dataSource != null) {
      let ds = this.dataSource;
      $.extend(options, {
        ajax: {
          dataType: 'json',
          delay: 250,
          data: function (params) {
            return {
              q: params.term, // search term
              page: params.page
            };
          },
          processResults: (data: any, page) => {
            let selected: number[] = this.value ? ((Array.isArray(this.value) ? this.value : [this.value]).map(x => x.id ? x.id : x)) : [];
            var cleanData = (data.results as any[]).map(item => {
              if (this.optionsValue != null && this.optionsText != null) {
                let treated = {
                  id: item[this.optionsValue],
                  text: UIInternal.getValue(item, this.optionsText),
                  data: item
                }
                // Remove already selected
                return selected.find(id => id == treated.id) != null ? null : treated;
              }
            });
            // parse the results into the format expected by Select2.
            // since we are using custom formatting functions we do not need to
            // alter the remote JSON data
            //if (cleanData === []) debugger;
            let result = {
              results: cleanData.filter(o => !!o),
              pagination: {
                more: data.more
              }
            };

            if (false == this.multiple && this.submitOnLoad.isSubmitting) {
              // Did ENTER during load, select value
              this.submitOnLoad.isSubmitting = false;
              if (result.results.length > 0) {
                UIInternal.nextTick(() => {
                  this.value = result.results[0].id;
                  this.valueChanged(this.value, null);
                  this.close();
                });
              }
            }

            return result;
          },
          transport: (params, success, failure) => {
            this.submitOnLoad.isLoading = true;
            var fail = () => {
              this.submitOnLoad.isLoading = false;
            };
            let currentPage = params.data.page != null ? params.data.page : 1;
            let startRow = (currentPage - 1) * this.pageSize;
            let endRow = startRow + this.pageSize;
            let currentCallNumber = ++this.callNumber;

            var callBack = (rowsThisPage: any[], lastRow?: number) => {
              // Drop results comming in the wrong order
              if (currentCallNumber == this.callNumber) {
                this.submitOnLoad.isLoading = false;
                success({
                  results: rowsThisPage,
                  more: lastRow > endRow
                });
              }
            };
            var p: any = {
              startRow: startRow,
              endRow: endRow,
              successCallback: callBack,
              failCallback: failure,
              sortModel: [
                { colId: this.replaceTranslation(this.optionsText), sort: 'ASC' }
              ]

            };
            let sortModel = this.getSortModelFromSortColumn(this.sortColumn);
            if (sortModel != null && sortModel.length > 0) {
              p.sortModel = sortModel;
            }
            ds.getRowsForSelect2(p, params.data.q, this.evalFilterProperties);
            return ds;
          }
        }
      });
    }
    options.escapeMarkup = function (markup) { return markup; }; // let our custom formatter work
    options.minimumInputLength = minimumInputLength;
    options.closeOnSelect = true;
    options.tags = this.tags;

    options.language = <Translation>{
      errorLoading: () => this.i18n.tr("select2.errorLoading", { ns: "common" }),
      inputTooShort: () => this.i18n.tr("select2.inputTooShort", { ns: "common" }),
      loadingMore: () => this.i18n.tr("select2.loadingMore", { ns: "common" }),
      noResults: () => this.i18n.tr("select2.noResults", { ns: "common" }),
      searching: () => this.i18n.tr("select2.searching", { ns: "common" })
    };
    this.setupSelect2CustomAdapters(options);
    options.templateSelection = this.getTemplateSelection;
    options.templateResult = this.getTemplateFromSelect2;
    options.width = "100%";
    options.dropdownAutoWidth = this.dropdownAutoWidth;
    return options;
  }

  private get evalFilterProperties(): string[] {
    if (this.filterProperties != null && this.filterProperties.length > 0) {
      let filterProperties = eval(this.filterProperties) as string[];
      return filterProperties.map(x => this.replaceTranslation(x));
    }
    return [];
  }

  private setupSelect2CustomAdapters(options: Options) {
    var Utils = jQuery.fn.select2.amd.require('select2/utils');
    if (options.dropdownAdapter == null) {
      if (options.multiple) {
        options.dropdownAdapter = CustomDropdownAdapter;
      } else {
        var Search = jQuery.fn.select2.amd.require('select2/dropdown/search');
        var SearchableDropdown = Utils.Decorate(CustomDropdownAdapter, Search);

        options.dropdownAdapter = SearchableDropdown;
      }
      if (options.minimumResultsForSearch !== 0) {
        var MinimumResultsForSearch = jQuery.fn.select2.amd.require('select2/dropdown/minimumResultsForSearch');
        options.dropdownAdapter = Utils.Decorate(
          options.dropdownAdapter,
          MinimumResultsForSearch
        );
      }
      if (options.closeOnSelect) {
        var CloseOnSelect = jQuery.fn.select2.amd.require('select2/dropdown/closeOnSelect');
        options.dropdownAdapter = Utils.Decorate(
          options.dropdownAdapter,
          CloseOnSelect
        );
      }
      if (this.dropdownCssClass?.length > 0) {
        options.dropdownCssClass = this.dropdownCssClass;
      }
      if (options.dropdownCssClass != null) {
        var DropdownCSS = jQuery.fn.select2.amd.require('select2/dropdown/dropdownCss');
        options.dropdownAdapter = Utils.Decorate(
          options.dropdownAdapter,
          DropdownCSS
        );
      }
      options.dropdownAdapter = Utils.Decorate(
        options.dropdownAdapter,
        customAttachBody
      );
    }
    if (options.dataAdapter == null) {
      var ArrayData = jQuery.fn.select2.amd.require('select2/data/array');
      var SelectData = jQuery.fn.select2.amd.require('select2/data/select');
      var MinimumInputLength = jQuery.fn.select2.amd.require('select2/data/minimumInputLength');
      var MaximumInputLength = jQuery.fn.select2.amd.require('select2/data/maximumInputLength');
      var MaximumSelectionLength = jQuery.fn.select2.amd.require('select2/data/maximumSelectionLength');
      var Tokenizer = jQuery.fn.select2.amd.require('select2/data/tokenizer');
      var Tags = jQuery.fn.select2.amd.require('select2/data/tags');
      if (options.ajax != null) {
        options.dataAdapter = CustomAjaxAdapter;
      } else if (options.data != null) {
        options.dataAdapter = ArrayData;
      } else {
        options.dataAdapter = CustomSelectAdapter;
      }

      if (options.minimumInputLength > 0) {
        options.dataAdapter = Utils.Decorate(
          options.dataAdapter,
          MinimumInputLength
        );
      }

      if (options.maximumInputLength > 0) {
        options.dataAdapter = Utils.Decorate(
          options.dataAdapter,
          MaximumInputLength
        );
      }

      if (options.maximumSelectionLength > 0) {
        options.dataAdapter = Utils.Decorate(
          options.dataAdapter,
          MaximumSelectionLength
        );
      }

      if (options.tags) {
        options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);
      }

      if (options.tokenSeparators != null || options.tokenizer != null) {
        options.dataAdapter = Utils.Decorate(
          options.dataAdapter,
          Tokenizer
        );
      }
    }
    options.multiple = this.multiple;
    options.allowClear = this.allowClear;

    if (options.selectionAdapter == null) {
      var SingleSelection = jQuery.fn.select2.amd.require('select2/selection/single');
      var SelectionSearch = jQuery.fn.select2.amd.require('select2/selection/search');
      var Placeholder = jQuery.fn.select2.amd.require('select2/selection/placeholder');
      var SelectionCSS = jQuery.fn.select2.amd.require('select2/selection/selectionCss');
      var EventRelay = jQuery.fn.select2.amd.require('select2/selection/eventRelay');

      if (options.multiple) {
        options.selectionAdapter = CustomMultipleSelection;
        options.selectionAdapter = Utils.Decorate(
          options.selectionAdapter,
          SelectionSearch
        );
      } else {
        options.selectionAdapter = SingleSelection;
      }

      if (options.allowClear) {
        options.selectionAdapter = Utils.Decorate(
          options.selectionAdapter,
          CustomAllowClear
        );
      }

      if (options.placeholder != null) {
        options.selectionAdapter = Utils.Decorate(
          options.selectionAdapter,
          Placeholder
        );
      }

      if ((options as any).selectionCssClass != null) {
        options.selectionAdapter = Utils.Decorate(
          options.selectionAdapter,
          SelectionCSS
        );
      }

      options.selectionAdapter = Utils.Decorate(
        options.selectionAdapter,
        EventRelay
      );
    }
  }

  private getSortModelFromSortColumn(sortColumn: string) {
    if (sortColumn == null || sortColumn.length == 0) return null;
    let sortModel = [];
    if (sortColumn.indexOf(',') > -1) {
      var sortColumns = sortColumn.split(',');
      sortColumns.forEach(col => {
        sortModel.push({
          colId: this.replaceTranslation(col),
          sort: this.getSortDirection(col)
        });
      });
    }
    else {
      sortModel.push({
        colId: this.replaceTranslation(sortColumn),
        sort: this.getSortDirection(sortColumn)
      });
    }
    return sortModel;
  }
  private getSortDirection(col: string) {
    if (col.indexOf(' ') > -1) {
      return col.split(' ')[1];
    }
    else return 'ASC';
  }
  private replaceTranslation(col: string) {
    if (col.indexOf('_translation') > -1) {
      return col.replace('_translation', this.datacontext.translatePropertyName);
    }
    return col;
  }

  private resizeSelection(hasSelection: boolean) {
    if (this.onSelectedSize != null) {
      let el = $(this.element).find('.select2-selection');
      el.css('height', hasSelection ? this.onSelectedSize : '');
    }
  }

  valueChanged(newVal, oldVal) {
    if (this.$select) {
      if (newVal != oldVal) {
        const $options = $(this.element).find('option');
        // $options.removeAttr('data-select2-id');
        const Utils = jQuery.fn.select2.amd.require('select2/utils');
        $options.each((index, element) => Utils.RemoveData(element));
        if (this.value != null && Object.keys(this.value).length > 0 && Object.keys(this.value).indexOf('id') > -1) {
          this.taskQueue.queueMicroTask(() => {
            this.$select.val(newVal.id).trigger("change");
            this.callOnChangeCallback(newVal);
            this.resizeSelection(true);
          });

        }
        else {
          UIInternal.queueTask(() => {
            if (newVal == null) {
              this.$select.val('').trigger("change");
              this.select2Instance.$selection.find('.select2-selection__clear').remove();
              this.callOnChangeCallback('');
              this.resizeSelection(false);
            } else {
              this.$select.val(newVal).trigger("change");
              this.callOnChangeCallback(newVal);
              this.resizeSelection(true);
            }
            this.manageSelectionTitle();
          });
        }
      }
    }
  }

  placeholderChanged(newVal, oldVal) {
    if (this.$select) {
      if (newVal != oldVal) {
        UIInternal.queueTask(() => {
          // We need to pass the entire options object or else the missing options are removed
          this.$select.select2(this.fillOptions());
        })

      }
    }
  }
  dataSourceChanged(newVal, oldVal) {
    if (this.$select) {
      if (newVal != oldVal) {
        // We need to pass the entire options object or else the missing options are removed
        this.$select.select2(this.fillOptions());
      }
    }
  }

  public close() {
    this.$select.select2('close');
  }
  public closeOnClickHandler = () => { this.close(); }

  public open() {
    this.$select.select2('open');
  }

  /**
   * Hide the selected value _title_ element attribute if this.selectionTitle is false.
   *
   * @private
   * @memberof UISelect
   */
  private manageSelectionTitle(): void {
    if (this.selectionTitle == false || this.selectionTitle == 'false') {
      let elementWithTitle = this.select2Instance.$container.find('.select2-selection__rendered');
      if (elementWithTitle != null) {
        elementWithTitle.removeAttr('title');
      }
    }
  }

  detached() {
    this.close();
    this.clickableElements?.forEach(elem => elem.removeEventListener("click", this.closeOnClickHandler));
    this.onChangeCollectionObserverDisposables.forEach(d => d.dispose());
    this.changeLanguageSubscription?.dispose();
  }

  private callOnChangeCallback(value: any) {
    if (this.onChange) {
      this.onChange({ value: value });
    }
  }
}

function makePartReplacementFromContent(_viewCompiler, _viewResources, element: HTMLElement, instruction: any) {
  const content = element.firstElementChild;
  instruction.inheritBindingContext = true;
  if (content) {
    const template = document.createElement('template');
    template.setAttribute('replace-part', 'options');
    element.children.forEach((child: HTMLElement) => {
      //element.removeChild(child);
      if (child instanceof HTMLOptionElement) {
        template.content.appendChild(child.cloneNode(true));
      } else if (child.tagName.toUpperCase() === "UI-SELECT-ITEM-TEMPLATE") {
        instruction.itemTemplate = child.innerHTML;
      } else if (child.tagName.toUpperCase() === "UI-SELECT-HEADER-TEMPLATE") {
        instruction.headerTemplate = child.innerHTML;
        if (child.hasAttribute("close-on-click")) {
          instruction.closeOnHeaderClick = true;
        }
      } else if (child.tagName.toUpperCase() === "UI-SELECT-FOOTER-TEMPLATE") {
        instruction.footerTemplate = child.innerHTML;
        if (child.hasAttribute("close-on-click")) {
          instruction.closeOnFooterClick = true;
        }
      } else if (child.tagName.toUpperCase() === "UI-SELECT-SELECTION-TEMPLATE") {
        instruction.selectionTemplate = child.innerHTML;
      }
    });
    while (element.firstChild) {
      element.removeChild(element.firstChild);
    }
    element.appendChild(template);
    return true;
  }
}


