text: import { hooks } from '@bigcommerce/stencil-utils';
  import CatalogPage from './catalog';
  import FacetedSearch from './common/faceted-search';
  import compareProducts from './global/compare-products';
  import urlUtils from './common/url-utils';
  import Url from 'url';
  import collapsibleFactory from './common/collapsible';
  import 'jstree';
  import nod from './common/nod';
  
  export default class Search extends CatalogPage {
      formatCategoryTreeForJSTree(node) {
          const nodeData = {
              text: node.data,
              id: node.metadata.id,
              state: {
                  selected: node.selected,
              },
          };
  
          if (node.state) {
              nodeData.state.opened = node.state === 'open';
              nodeData.children = true;
          }
  
          if (node.children) {
              nodeData.children = [];
              node.children.forEach((childNode) => {
                  nodeData.children.push(this.formatCategoryTreeForJSTree(childNode));
              });
          }
  
          return nodeData;
      }
  
      showProducts() {
          const url = urlUtils.replaceParams(window.location.href, {
              section: 'product',
          });
  
          this.$productListingContainer.removeClass('u-hiddenVisually');
          this.$facetedSearchContainer.removeClass('u-hiddenVisually');
          this.$contentResultsContainer.addClass('u-hiddenVisually');
  
          $('[data-content-results-toggle]').removeClass('navBar-action-color--active');
          $('[data-content-results-toggle]').addClass('navBar-action');
  
          $('[data-product-results-toggle]').removeClass('navBar-action');
          $('[data-product-results-toggle]').addClass('navBar-action-color--active');
  
          urlUtils.goToUrl(url);
      }
  
      showContent() {
          const url = urlUtils.replaceParams(window.location.href, {
              section: 'content',
          });
  
          this.$contentResultsContainer.removeClass('u-hiddenVisually');
          this.$productListingContainer.addClass('u-hiddenVisually');
          this.$facetedSearchContainer.addClass('u-hiddenVisually');
  
          $('[data-product-results-toggle]').removeClass('navBar-action-color--active');
          $('[data-product-results-toggle]').addClass('navBar-action');
  
          $('[data-content-results-toggle]').removeClass('navBar-action');
          $('[data-content-results-toggle]').addClass('navBar-action-color--active');
  
          urlUtils.goToUrl(url);
      }
  
      onReady() {
          compareProducts(this.context.urls);
  
          const $searchForm = $('[data-advanced-search-form]');
          const $categoryTreeContainer = $searchForm.find('[data-search-category-tree]');
          const url = Url.parse(window.location.href, true);
          const treeData = [];
          this.$productListingContainer = $('#product-listing-container');
          this.$facetedSearchContainer = $('#faceted-search-container');
          this.$contentResultsContainer = $('#search-results-content');
  
          // Init faceted search
          if ($('#facetedSearch').length > 0) {
              this.initFacetedSearch();
          } else {
              this.onSortBySubmit = this.onSortBySubmit.bind(this);
              hooks.on('sortBy-submitted', this.onSortBySubmit);
          }
  
          // Init collapsibles
          collapsibleFactory();
  
          $('[data-product-results-toggle]').on('click', event => {
              event.preventDefault();
              this.showProducts();
          });
  
          $('[data-content-results-toggle]').on('click', event => {
              event.preventDefault();
              this.showContent();
          });
  
          if (this.$productListingContainer.find('li.product').length === 0 || url.query.section === 'content') {
              this.showContent();
          } else {
              this.showProducts();
          }
  
          const validator = this.initValidation($searchForm)
              .bindValidation($searchForm.find('#search_query_adv'));
  
          this.context.categoryTree.forEach((node) => {
              treeData.push(this.formatCategoryTreeForJSTree(node));
          });
  
          this.categoryTreeData = treeData;
          this.createCategoryTree($categoryTreeContainer);
  
          $searchForm.on('submit', event => {
              const selectedCategoryIds = $categoryTreeContainer.jstree().get_selected();
  
              if (!validator.check()) {
                  return event.preventDefault();
              }
  
              $searchForm.find('input[name="category\[\]"]').remove();
  
              for (const categoryId of selectedCategoryIds) {
                  const input = $('<input>', {
                      type: 'hidden',
                      name: 'category[]',
                      value: categoryId,
                  });
  
                  $searchForm.append(input);
              }
          });
      }
  
      loadTreeNodes(node, cb) {
          $.ajax({
              url: '/remote/v1/category-tree',
              data: {
                  selectedCategoryId: node.id,
                  prefix: 'category',
              },
          }).done(data => {
              const formattedResults = [];
  
              data.forEach((dataNode) => {
                  formattedResults.push(this.formatCategoryTreeForJSTree(dataNode));
              });
  
              cb(formattedResults);
          });
      }
  
      createCategoryTree($container) {
          const treeOptions = {
              core: {
                  data: (node, cb) => {
                      // Root node
                      if (node.id === '#') {
                          cb(this.categoryTreeData);
                      } else {
                          // Lazy loaded children
                          this.loadTreeNodes(node, cb);
                      }
                  },
                  themes: {
                      icons: true,
                  },
              },
              checkbox: {
                  three_state: false,
              },
              plugins: [
                  'checkbox',
              ],
          };
  
          $container.jstree(treeOptions);
      }
  
      initFacetedSearch() {
          const $productListingContainer = $('#product-listing-container');
          const $facetedSearchContainer = $('#faceted-search-container');
          const $searchHeading = $('#search-results-heading');
          const $searchCount = $('#search-results-product-count');
          const productsPerPage = this.context.searchProductsPerPage;
          const requestOptions = {
              template: {
                  productListing: 'search/product-listing',
                  sidebar: 'search/sidebar',
                  heading: 'search/heading',
                  productCount: 'search/product-count',
              },
              config: {
                  product_results: {
                      limit: productsPerPage,
                  },
              },
              showMore: 'search/show-more',
          };
  
          this.facetedSearch = new FacetedSearch(requestOptions, (content) => {
              $productListingContainer.html(content.productListing);
              $facetedSearchContainer.html(content.sidebar);
              $searchHeading.html(content.heading);
              $searchCount.html(content.productCount);
  
              $('html, body').animate({
                  scrollTop: 0,
              }, 100);
          });
      }
  
      initValidation($form) {
          this.$form = $form;
          this.validator = nod({
              submit: $form,
          });
  
          return this;
      }
  
      bindValidation($element) {
          if (this.validator) {
              this.validator.add({
                  selector: $element,
                  validate: 'presence',
                  errorMessage: $element.data('errorMessage'),
              });
          }
  
          return this;
      }
  
      check() {
          if (this.validator) {
              this.validator.performCheck();
              return this.validator.areAll('valid');
          }
  
          return false;
      }
  }
  