import React, { createRef } from 'react';
import { loadModules } from 'esri-loader';
// import { FontAwesomeIcon } from '@eeacms/volto-clms-utils/components';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

var WMSLayer, WMTSLayer, WFSLayer, esriRequest;
const SHAPEFILE_MAX_SIZE_BYTES = 2097152;

class UploadWidget extends React.Component {
  /**
   * Creator of the Upload widget class
   * @param {*} props
   */
  constructor(props) {
    super(props);
    //We create a reference to a DOM element to be mounted
    this.container = createRef();
    //Initially, we set the state of the component to
    //not be showing the basemap panel
    this.state = {
      showMapMenu: false,
      showInfoPopup: false,
      infoPopupType: '',
      serviceUrl: '',
      selectedServiceType: '',
      wfsFeatures: {},
      selectedFeatures: {},
      activeTab: 'url',
      globalDragActive: false,
    };
    this.menuClass =
      'esri-icon-sketch-rectangle esri-widget--button esri-widget esri-interactive';
    this.mapviewer_config = this.props.mapviewer_config;
    this.fileInput = createRef();
    this.uploadUrlServiceHandler = this.props.uploadUrlServiceHandler;
    this.uploadFileErrorHandler = this.props.uploadFileErrorHandler;
    this.errorPopup = this.errorPopup.bind(this);
    this.setActiveTab = this.setActiveTab.bind(this);
    this.handleBrowseClick = this.handleBrowseClick.bind(this);
    this.handleFileSelected = this.handleFileSelected.bind(this);
    this.handleDragOver = this.handleDragOver.bind(this);
    this.handleDrop = this.handleDrop.bind(this);
    this.handleAddClick = this.handleAddClick.bind(this);
    this.clearSelectedFile = this.clearSelectedFile.bind(this);
    this.isComponentMounted = false;
    this.infoPopupTimeout = null;
  }

  loader() {
    return loadModules([
      'esri/layers/WMSLayer',
      'esri/layers/WMTSLayer',
      'esri/layers/WFSLayer',
      'esri/request',
    ]).then(([_WMSLayer, _WMTSLayer, _WFSLayer, _esriRequest]) => {
      [WMSLayer, WMTSLayer, WFSLayer, esriRequest] = [
        _WMSLayer,
        _WMTSLayer,
        _WFSLayer,
        _esriRequest,
      ];
    });
  }

  /**
   * Method that will be invoked when the
   * button is clicked. It controls the open
   * and close actions of the component
   */
  openMenu() {
    if (this.state.showMapMenu) {
      this.props.mapViewer.setActiveWidget();
      this.container.current.querySelector('.right-panel').style.display =
        'none';
      this.container.current.querySelector(
        '.right-panel-content',
      ).style.overflowY = 'auto';
      this.container.current.querySelector(
        '.right-panel-content',
      ).style.display = 'none';
      this.container.current.querySelector(
        '.right-panel-content',
      ).style.alignItems = 'none';
      this.container.current.querySelector('.upload-panel').style.display =
        'none';
      this.container.current.querySelector('.upload-panel').style.flexWrap =
        'none';
      this.container.current
        .querySelector('.esri-widget--button')
        .classList.remove('active-widget');
      document
        .querySelector('.esri-ui-top-right.esri-ui-corner')
        .classList.remove('show-panel');
      // By invoking the setState, we notify the state we want to reach
      // and ensure that the component is rendered again
      this.setState({
        showMapMenu: false,
        showInfoPopup: false,
        infoPopupType: '',
      });
      this.clearWidget();
    } else {
      this.props.mapViewer.setActiveWidget(this);
      this.container.current.querySelector('.right-panel').style.display =
        'flex';
      this.container.current.querySelector(
        '.right-panel-content',
      ).style.overflowY = 'hidden';
      this.container.current.querySelector(
        '.right-panel-content',
      ).style.display = 'flex';
      this.container.current.querySelector(
        '.right-panel-content',
      ).style.alignItems = 'center';
      this.container.current.querySelector('.upload-panel').style.display =
        'flex';
      this.container.current.querySelector('.upload-panel').style.flexWrap =
        'wrap';
      this.container.current
        .querySelector('.esri-widget--button')
        .classList.add('active-widget');
      document
        .querySelector('.esri-ui-top-right.esri-ui-corner')
        .classList.add('show-panel');
      // By invoking the setState, we notify the state we want to reach
      // and ensure that the component is rendered again
      this.setState({
        showMapMenu: true,
        showInfoPopup: false,
        infoPopupType: '',
      });
    }
  }

  clearWidget() {
    window.document.querySelector('.pan-container').style.display = 'none';
    this.props.mapViewer.view.popup.close();
    //const { wmsLayer } = this.state;
    //if (wmsLayer) {
    //  this.props.view.map.remove(wmsLayer);
    //  // this.props.view.graphics.removeAll();
    //}
    //this.setState({
    //  wmsLayer: null,
    //  serviceUrl: '',
    //});

    document.querySelector('.esri-attribution__powered-by').style.display =
      'none';
  }

  handleserviceUrlChange = (event) => {
    this.setState({ serviceUrl: event.target.value });
  };

  buildUploadResetState = () => {
    return {
      serviceUrl: '',
      wfsFeatures: {},
      selectedFeatures: {},
      selectedFile: null,
      showInfoPopup: false,
      infoPopupType: '',
      globalDragActive: false,
    };
  };

  handleServiceTypeChange = (event) => {
    const nextServiceType = event.target.value;
    this.setState((prevState) => {
      if (prevState.selectedServiceType === nextServiceType) {
        return null;
      }
      return {
        selectedServiceType: nextServiceType,
        ...this.buildUploadResetState(),
      };
    });
    if (this.fileInput && this.fileInput.current) {
      this.fileInput.current.value = null;
    }
  };

  setActiveTab(tab) {
    this.setState({ activeTab: tab });
  }

  handleBrowseClick() {
    if (this.fileInput && this.fileInput.current) {
      this.fileInput.current.click();
    }
  }

  handleFileSelected(e) {
    const file = e.target.files && e.target.files[0];
    if (!file) {
      return;
    }
    this.processInputPayload(file);
    e.target.value = null;
  }

  resolveInputError(filePayload) {
    const inputName = ((filePayload && filePayload.name) || '').toLowerCase();
    const inputExtension = inputName.split('.').pop();
    if (inputExtension !== 'zip') {
      return 'fileUploadError';
    }
    const inputSize = (filePayload && filePayload.size) || 0;
    if (inputSize > SHAPEFILE_MAX_SIZE_BYTES) {
      return 'shapefileLimit';
    }
    return null;
  }

  processInputPayload(filePayload) {
    const inputError = this.resolveInputError(filePayload);
    if (inputError) {
      this.setState({
        showInfoPopup: true,
        infoPopupType: inputError,
        selectedFile: null,
        globalDragActive: false,
      });
      if (typeof this.uploadFileErrorHandler === 'function') {
        this.uploadFileErrorHandler(inputError);
      }
      return false;
    }
    this.setState({ selectedFile: filePayload, globalDragActive: false });
    return true;
  }

  getNormalizedUrlForType = (serviceUrl, serviceType) => {
    if (serviceType === 'WMTS') {
      try {
        const parsedUrl = new URL(serviceUrl);
        const pathName = parsedUrl.pathname;
        const searchQuery = parsedUrl.search.toLowerCase();
        if (
          pathName.includes('/wmts/') &&
          searchQuery.includes('request=gettile')
        ) {
          const pathParts = pathName.split('/').filter(Boolean);
          const wmtsIndex = pathParts.indexOf('wmts');
          const projection = pathParts[wmtsIndex + 1] || '';
          const variant = pathParts[wmtsIndex + 2] || '';
          if (projection && variant) {
            return (
              parsedUrl.origin +
              '/wmts/' +
              projection +
              '/' +
              variant +
              '/1.0.0/WMTSCapabilities.xml'
            );
          }
        }
      } catch (error) {}
    }
    return serviceUrl;
  };

  isValidUrl = (url) => {
    try {
      new URL(url);
      return true;
    } catch (e) {
      return false;
    }
  };

  getServiceTypeFromUrl = (serviceUrl) => {
    try {
      const parsedUrl = new URL(serviceUrl);
      const queryService = (parsedUrl.searchParams.get('service') || '')
        .trim()
        .toUpperCase();
      if (
        queryService === 'WMS' ||
        queryService === 'WMTS' ||
        queryService === 'WFS'
      ) {
        return queryService;
      }
      const pathName = (parsedUrl.pathname || '').toLowerCase();
      const pathSegments = pathName.split('/').filter(Boolean);
      const serviceMatch = pathSegments.find((segment) =>
        /^(wmts|wms|wfs)$/i.test(segment),
      );
      if (serviceMatch) {
        return serviceMatch.toUpperCase();
      }
      return null;
    } catch (e) {
      return null;
    }
  };

  isServiceTypeMatchingUrl = (serviceUrl, selectedServiceType) => {
    const encodedServiceType = this.getServiceTypeFromUrl(serviceUrl);
    if (!encodedServiceType) {
      return true;
    }
    return encodedServiceType === selectedServiceType;
  };

  stripProtocol = (url) => {
    return (url || '').replace(/^https?:\/\//i, '');
  };

  getProxyBase = () => {
    // const href = window.location.href || '';
    // return href.replace('/en/map-viewer', '/ogcproxy/');
    return 'https://clmsdemo.devel6cph.eea.europa.eu/ogcproxy/';
  };

  buildProxiedUrl = (url) => {
    return this.getProxyBase() + this.stripProtocol(url);
  };

  resolveNodeValue = (nodeValue) => {
    if (nodeValue === null || nodeValue === undefined) {
      return null;
    }
    if (typeof nodeValue === 'string' || typeof nodeValue === 'number') {
      const textValue = String(nodeValue).trim();
      return textValue === '' ? null : textValue;
    }
    if (Array.isArray(nodeValue)) {
      for (let i = 0; i < nodeValue.length; i += 1) {
        const resolvedValue = this.resolveNodeValue(nodeValue[i]);
        if (resolvedValue) {
          return resolvedValue;
        }
      }
      return null;
    }
    if (typeof nodeValue === 'object') {
      if (Object.prototype.hasOwnProperty.call(nodeValue, '#text')) {
        return this.resolveNodeValue(nodeValue['#text']);
      }
      if (Object.prototype.hasOwnProperty.call(nodeValue, '_')) {
        return this.resolveNodeValue(nodeValue._);
      }
      if (Object.prototype.hasOwnProperty.call(nodeValue, '$t')) {
        return this.resolveNodeValue(nodeValue.$t);
      }
      if (Object.prototype.hasOwnProperty.call(nodeValue, 'value')) {
        return this.resolveNodeValue(nodeValue.value);
      }
    }
    return null;
  };

  processXmlCapabilitiesData = (xmlInput) => {
    let xmlDoc = xmlInput;
    if (typeof xmlInput === 'string') {
      const parser = new DOMParser();
      xmlDoc = parser.parseFromString(xmlInput, 'text/xml');
    }
    if (!xmlDoc || typeof xmlDoc.querySelectorAll !== 'function') {
      return null;
    }
    const featureTypeList = [];
    const featureTypes = xmlDoc.querySelectorAll('FeatureType, featuretype');
    featureTypes.forEach((featureTypeNode) => {
      const titleNode =
        featureTypeNode.querySelector('Title') ||
        featureTypeNode.querySelector('title') ||
        featureTypeNode.querySelector('ows\\:Title');
      const nameNode =
        featureTypeNode.querySelector('Name') ||
        featureTypeNode.querySelector('name') ||
        featureTypeNode.querySelector('wfs\\:Name') ||
        featureTypeNode.querySelector('ows\\:Identifier');
      const nameValue = this.resolveNodeValue(nameNode && nameNode.textContent);
      const titleValue = this.resolveNodeValue(
        titleNode && titleNode.textContent,
      );
      if (nameValue) {
        featureTypeList.push({
          Name: nameValue,
          Title: titleValue,
        });
      }
    });
    return {
      FeatureTypeList: {
        FeatureType: featureTypeList,
      },
    };
  };

  resolveCapabilitiesData = (capabilitiesResponse) => {
    if (
      capabilitiesResponse &&
      typeof capabilitiesResponse === 'object' &&
      !Array.isArray(capabilitiesResponse) &&
      typeof capabilitiesResponse.querySelectorAll !== 'function'
    ) {
      return capabilitiesResponse;
    }
    if (typeof capabilitiesResponse === 'string') {
      const trimmedResponse = capabilitiesResponse.trim();
      if (trimmedResponse === '') {
        return null;
      }
      try {
        return JSON.parse(trimmedResponse);
      } catch (e) {
        return this.processXmlCapabilitiesData(trimmedResponse);
      }
    }
    if (
      capabilitiesResponse &&
      typeof capabilitiesResponse === 'object' &&
      typeof capabilitiesResponse.querySelectorAll === 'function'
    ) {
      return this.processXmlCapabilitiesData(capabilitiesResponse);
    }
    return null;
  };

  resolveFeatureTypeList = (capabilitiesData) => {
    const featureTypeList = [];
    const processNode = (nodeValue) => {
      if (nodeValue === null || nodeValue === undefined) {
        return;
      }
      if (Array.isArray(nodeValue)) {
        nodeValue.forEach((itemValue) => {
          processNode(itemValue);
        });
        return;
      }
      if (typeof nodeValue !== 'object') {
        return;
      }
      const nameValue = this.resolveNodeValue(
        nodeValue.Name ||
          nodeValue.name ||
          nodeValue['wfs:Name'] ||
          nodeValue['ows:Identifier'],
      );
      const titleValue = this.resolveNodeValue(
        nodeValue.Title || nodeValue.title || nodeValue['ows:Title'],
      );
      if (nameValue) {
        featureTypeList.push({
          Name: nameValue,
          Title: titleValue,
        });
      }
      const nestedFeatureType =
        nodeValue.FeatureType || nodeValue.featureType || nodeValue.featuretype;
      if (nestedFeatureType) {
        processNode(nestedFeatureType);
      }
      Object.keys(nodeValue).forEach((keyValue) => {
        if (
          keyValue !== 'FeatureType' &&
          keyValue !== 'featureType' &&
          keyValue !== 'featuretype'
        ) {
          processNode(nodeValue[keyValue]);
        }
      });
    };
    processNode(capabilitiesData);
    return featureTypeList;
  };

  getCapabilities = (url, serviceType) => {
    // Get the coordinates of the click on the view
    const proxiedUrl = this.buildProxiedUrl(url);
    return esriRequest(proxiedUrl, {
      responseType: 'text',
      query: {
        request: 'GetCapabilities',
        service: serviceType,
        version: serviceType === 'WFS' ? '2.0.0' : '1.3.0',
      },
    })
      .then((response) => {
        const capabilitiesData = this.resolveCapabilitiesData(response.data);
        this.capabilitiesData = capabilitiesData;
      })
      .catch(() => {});
  };

  parseWFSFeatures = (capabilitiesData) => {
    try {
      const features = {};
      const featureTypeList = this.resolveFeatureTypeList(capabilitiesData);
      featureTypeList.forEach((featureTypeValue) => {
        const key = this.resolveNodeValue(featureTypeValue.Name);
        const title = this.resolveNodeValue(featureTypeValue.Title);
        if (key) {
          features[key] = title ?? null;
        }
      });
      return features;
    } catch (e) {
      return {};
    }
  };

  handleFeatureCheckboxChange = (event) => {
    const key = event.target.value;
    const { wfsFeatures, selectedFeatures } = this.state;
    const nextSelected = { ...selectedFeatures };
    if (event.target.checked) {
      if (wfsFeatures && wfsFeatures[key]) {
        nextSelected[key] = wfsFeatures[key];
      } else {
        nextSelected[key] = key;
      }
    } else {
      if (Object.prototype.hasOwnProperty.call(nextSelected, key)) {
        delete nextSelected[key];
      }
    }
    this.setState({ selectedFeatures: nextSelected });
  };

  handleSelectLayers = async () => {
    const { serviceUrl, selectedServiceType } = this.state;
    const trimmedServiceUrl = (serviceUrl || '').trim();
    if (
      selectedServiceType === 'WFS' &&
      trimmedServiceUrl !== '' &&
      this.isValidUrl(trimmedServiceUrl) &&
      this.isServiceTypeMatchingUrl(trimmedServiceUrl, selectedServiceType)
    ) {
      const normalizedUrl = this.getNormalizedUrlForType(
        trimmedServiceUrl,
        selectedServiceType,
      );
      await this.getCapabilities(normalizedUrl, selectedServiceType);
      const result = this.parseWFSFeatures(this.capabilitiesData);
      this.setState(() => ({
        wfsFeatures: result,
      }));
    } else {
      this.errorPopup();
    }
  };

  handleUploadService = async () => {
    const serviceUrl = this.state.serviceUrl;
    const trimmedServiceUrl = (serviceUrl || '').trim();
    const selectedServiceType = this.state.selectedServiceType;
    const selectedFeatures = this.state.selectedFeatures;
    if (
      selectedServiceType &&
      trimmedServiceUrl !== '' &&
      this.isValidUrl(trimmedServiceUrl) &&
      this.isServiceTypeMatchingUrl(trimmedServiceUrl, selectedServiceType)
    ) {
      const normalizedUrl = this.getNormalizedUrlForType(
        trimmedServiceUrl,
        selectedServiceType,
      );
      const proxiedUrl = this.buildProxiedUrl(normalizedUrl);
      if (selectedServiceType === 'WMS') {
        this.uploadUrlServiceHandler(proxiedUrl, 'WMS');
        this.setState({ serviceUrl: '' });
      } else if (selectedServiceType === 'WMTS') {
        this.uploadUrlServiceHandler(proxiedUrl, 'WMTS');
        this.setState({ serviceUrl: '' });
      } else if (selectedServiceType === 'WFS') {
        this.uploadUrlServiceHandler(proxiedUrl, 'WFS', selectedFeatures);
        this.setState({ wfsFeatures: {}, serviceUrl: '' });
        this.setState({ selectedFeatures: {} });
      } else {
        this.errorPopup();
        this.setState({ serviceUrl: '' });
        return;
      }
    } else {
      this.errorPopup();
      this.setState({ serviceUrl: '' });
    }
  };

  uploadWMSService = (url) => {
    this.uploadUrlServiceHandler(url, 'WMS');
  };

  uploadWMTSService = (url) => {
    this.uploadUrlServiceHandler(url, 'WMTS');
  };

  uploadWFSService = (url) => {
    this.uploadUrlServiceHandler(url, 'WFS', this.state.selectedFeatures);
    this.setState({ wfsFeatures: {}, serviceUrl: '', selectedFeatures: {} });
  };

  errorPopup = (popupType = 'uploadError') => {
    if (!this.isComponentMounted) {
      return;
    }
    this.setState({
      showInfoPopup: true,
      infoPopupType: popupType,
    });
    if (this.infoPopupTimeout) {
      clearTimeout(this.infoPopupTimeout);
    }
    this.infoPopupTimeout = setTimeout(() => {
      if (!this.isComponentMounted) {
        return;
      }
      this.setState({
        showInfoPopup: false,
        infoPopupType: '',
      });
    }, 3000);
  };

  /**
   * This method is executed after the render method is executed
   */
  async componentDidMount() {
    this.isComponentMounted = true;
    await this.loader();
    if (!this.props.view || !this.props.view.when) {
      return;
    }
    this.props.view.when(() => {
      if (!this.isComponentMounted || !this.props.view || !this.props.view.ui) {
        return;
      }
      if (this.container.current) {
        this.props.view.ui.add(this.container.current, 'top-right');
      }
      //load an empty wms layer to use the variable
      const wmsLayer = new WMSLayer({
        url: '',
        title: 'WMS Layer',
      });
      const wmtsLayer = new WMTSLayer({
        url: '',
        title: 'WMTS Layer',
      });
      const wfsLayer = new WFSLayer({
        url: '',
        title: 'WFS Layer',
      });
      if (!this.isComponentMounted) {
        return;
      }
      this.setState({
        wmsLayer: wmsLayer,
        wmtsLayer: wmtsLayer,
        wfsLayer: wfsLayer,
      });
    });
    this.handleWindowDragEnter = (e) => {
      if (
        e &&
        e.dataTransfer &&
        Array.from(e.dataTransfer.types || []).includes('Files')
      ) {
        e.preventDefault();
        this.setState({ globalDragActive: true });
      }
    };
    this.handleWindowDragOver = (e) => {
      if (
        e &&
        e.dataTransfer &&
        Array.from(e.dataTransfer.types || []).includes('Files')
      ) {
        e.preventDefault();
      }
    };
    this.handleWindowDragLeave = (e) => {
      this.setState({ globalDragActive: false });
    };
    this.handleWindowDrop = (e) => {
      e.preventDefault();
      this.setState({ globalDragActive: false });
    };
    window.addEventListener('dragenter', this.handleWindowDragEnter);
    window.addEventListener('dragover', this.handleWindowDragOver);
    window.addEventListener('dragleave', this.handleWindowDragLeave);
    window.addEventListener('drop', this.handleWindowDrop);
  }

  componentWillUnmount() {
    this.isComponentMounted = false;
    if (this.infoPopupTimeout) {
      clearTimeout(this.infoPopupTimeout);
      this.infoPopupTimeout = null;
    }
    window.removeEventListener('dragenter', this.handleWindowDragEnter);
    window.removeEventListener('dragover', this.handleWindowDragOver);
    window.removeEventListener('dragleave', this.handleWindowDragLeave);
    window.removeEventListener('drop', this.handleWindowDrop);
    if (this.props.view && this.props.view.ui && this.container.current) {
      try {
        this.props.view.ui.remove(this.container.current);
      } catch (error) {}
    }
  }

  componentDidUpdate(prevProps, prevState) {
    if (!prevProps.showErrorPopup && this.props.showErrorPopup) {
      this.errorPopup(this.props.showErrorPopupType || 'uploadError');
    }
  }

  /**
   * This method renders the component
   * @returns jsx
   */
  render() {
    const selectedServiceType = this.state.selectedServiceType;
    const serviceUrl = this.state.serviceUrl;
    const wfsFeatures = this.state.wfsFeatures;
    const selectedFeatures = this.state.selectedFeatures;
    const activeTab = this.state.activeTab;
    const isUploadDisabled =
      !selectedServiceType ||
      !(serviceUrl && serviceUrl.trim() !== '') ||
      (selectedServiceType === 'WFS' &&
        Object.keys(wfsFeatures || {}).length > 0 &&
        Object.keys(selectedFeatures || {}).length === 0);
    return (
      <>
        <div ref={this.container} className="upload-container">
          <div tooltip="Add External Service" direction="left" type="widget">
            <div
              className={this.menuClass}
              id="map_upload_button"
              aria-label="External service upload"
              onClick={this.openMenu.bind(this)}
              onKeyDown={(e) => {
                if (
                  !e.altKey &&
                  e.code !== 'Tab' &&
                  !e.ctrlKey &&
                  e.code !== 'Delete' &&
                  !e.shiftKey &&
                  !e.code.startsWith('F')
                ) {
                  this.openMenu(this);
                }
              }}
              tabIndex="0"
              role="button"
            ></div>
          </div>
          <div className="right-panel">
            <div className="right-panel-header">
              <span>Add external service</span>
              <span
                className="map-menu-icon esri-icon-close"
                onClick={this.openMenu.bind(this)}
                onKeyDown={(e) => {
                  if (
                    !e.altKey &&
                    e.code !== 'Tab' &&
                    !e.ctrlKey &&
                    e.code !== 'Delete' &&
                    !e.shiftKey &&
                    !e.code.startsWith('F')
                  ) {
                    this.openMenu(this);
                  }
                }}
                tabIndex="0"
                role="button"
              ></span>
            </div>
            <div
              className="right-panel-content"
              style={{ position: 'relative' }}
            >
              <div className="upload-panel">
                <div
                  className="tab-nav"
                  style={{
                    display: 'flex',
                    gap: '8px',
                    width: '100%',
                    marginBottom: '14px',
                    borderBottom: '1px solid #e6e6e6',
                  }}
                >
                  <button
                    onClick={() => this.setActiveTab('url')}
                    tabIndex="0"
                    style={{
                      padding: '10px 16px',
                      border: '1px solid #e6e6e6',
                      borderBottom:
                        activeTab === 'url'
                          ? '2px solid #c0d36b'
                          : '1px solid #e6e6e6',
                      background: activeTab === 'url' ? '#ffffff' : '#f6f6f6',
                      cursor: 'pointer',
                      outline: 'none',
                    }}
                  >
                    URL
                  </button>
                  <button
                    onClick={() => this.setActiveTab('file')}
                    tabIndex="0"
                    style={{
                      padding: '10px 16px',
                      border: '1px solid #e6e6e6',
                      borderBottom:
                        activeTab === 'file'
                          ? '2px solid #c0d36b'
                          : '1px solid #e6e6e6',
                      background: activeTab === 'file' ? '#ffffff' : '#f6f6f6',
                      cursor: 'pointer',
                      outline: 'none',
                    }}
                  >
                    File
                  </button>
                </div>
                {activeTab === 'url' && (
                  <div className="ccl-form">
                    <div className="field">
                      <label>
                        Service type
                        <select
                          defaultValue=""
                          onBlur={this.handleServiceTypeChange}
                        >
                          <option value="">Select a service</option>
                          <option value="WMS">WMS</option>
                          <option value="WMTS">WMTS</option>
                          <option value="WFS">WFS</option>
                        </select>
                      </label>
                    </div>
                    <div className="field">
                      <label>
                        Map service address
                        <input
                          type="text"
                          placeholder="Add map service URL (https://...)"
                          value={this.state.serviceUrl}
                          onChange={this.handleserviceUrlChange}
                        />
                      </label>
                    </div>
                    {this.state.selectedServiceType === 'WFS' &&
                    Object.keys(this.state.wfsFeatures || {}).length === 0 ? (
                      <button
                        className="esri-button"
                        onClick={this.handleSelectLayers}
                        disabled={
                          !this.state.selectedServiceType ||
                          !(
                            this.state.serviceUrl &&
                            this.state.serviceUrl.trim() !== ''
                          )
                        }
                      >
                        Select Layers
                      </button>
                    ) : (
                      <button
                        className="esri-button"
                        onClick={this.handleUploadService}
                        disabled={isUploadDisabled}
                      >
                        Upload service
                      </button>
                    )}
                    {Object.keys(this.state.wfsFeatures || {}).length > 0 && (
                      <div
                        className="wfs-features-list"
                        style={{
                          overflowY: 'auto',
                          overflowX: 'auto',
                          maxHeight: '280px',
                          width: '100%',
                        }}
                      >
                        {Object.entries(this.state.wfsFeatures).map(
                          ([key, title]) => (
                            <label
                              key={key}
                              className="field"
                              style={{
                                display: 'flex',
                                alignItems: 'center',
                                gap: '8px',
                                margin: '6px 0',
                                whiteSpace: 'nowrap',
                              }}
                            >
                              <input
                                type="checkbox"
                                value={key}
                                onChange={this.handleFeatureCheckboxChange}
                                checked={
                                  this.state.selectedFeatures &&
                                  this.state.selectedFeatures[key]
                                    ? true
                                    : false
                                }
                                style={{ width: '18px', height: '18px' }}
                              />
                              <span>{title || key}</span>
                            </label>
                          ),
                        )}
                      </div>
                    )}
                  </div>
                )}
                {activeTab === 'file' && this.renderFileDropArea(false)}
              </div>
              <input
                type="file"
                ref={this.fileInput}
                accept=".zip"
                style={{ display: 'none' }}
                onChange={this.handleFileSelected}
              />
              {this.state.globalDragActive && this.state.showMapMenu && (
                <div
                  className="global-file-drop-overlay"
                  style={{
                    position: 'absolute',
                    top: 0,
                    left: 0,
                    right: 0,
                    bottom: 0,
                    background: 'rgba(255,255,255,0.85)',
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    zIndex: 10,
                  }}
                  onDragOver={this.handleDragOver}
                >
                  {this.renderFileDropArea(true)}
                </div>
              )}
            </div>
          </div>
          {this.state.showInfoPopup && (
            <div className="map-container popup-block">
              <div className="drawRectanglePopup-block">
                <div className="drawRectanglePopup-content">
                  {this.state.infoPopupType === 'uploadError' && (
                    <>
                      <span className="drawRectanglePopup-icon">
                        <FontAwesomeIcon icon={['fas', 'info-circle']} />
                      </span>
                      <div className="drawRectanglePopup-text">
                        Error uploading the map service.
                      </div>
                    </>
                  )}
                  {this.state.infoPopupType === 'fileUploadError' && (
                    <>
                      <span className="drawRectanglePopup-icon">
                        <FontAwesomeIcon icon={['fas', 'info-circle']} />
                      </span>
                      <div className="drawRectanglePopup-text">
                        Invalid file type. Please upload a .zip shapefile.
                      </div>
                    </>
                  )}
                  {this.state.infoPopupType === 'fileLimit' && (
                    <>
                      <span className="drawRectanglePopup-icon">
                        <FontAwesomeIcon icon={['fas', 'info-circle']} />
                      </span>
                      <div className="drawRectanglePopup-text">
                        File exceeds the max size allowed of 10MB.
                      </div>
                    </>
                  )}
                  {this.state.infoPopupType === 'shapefileLimit' && (
                    <>
                      <span className="drawRectanglePopup-icon">
                        <FontAwesomeIcon icon={['fas', 'info-circle']} />
                      </span>
                      <div className="drawRectanglePopup-text">
                        Uploading shapefiles files larger than 2MB is not
                        allowed.
                      </div>
                    </>
                  )}
                  {this.state.infoPopupType === 'noGeometryError' && (
                    <>
                      <span className="drawRectanglePopup-icon">
                        <FontAwesomeIcon icon={['fas', 'info-circle']} />
                      </span>
                      <div className="drawRectanglePopup-text">
                        Selected service has no geometry data and cannot be
                        displayed on the map.
                      </div>
                    </>
                  )}
                  {this.state.infoPopupType === 'sceneViewTilingError' && (
                    <>
                      <span className="drawRectanglePopup-icon">
                        <FontAwesomeIcon icon={['fas', 'info-circle']} />
                      </span>
                      <div className="drawRectanglePopup-text">
                        Incorrect tiling scheme for scene view. The service can
                        still be used in 2D map view.
                      </div>
                    </>
                  )}
                </div>
              </div>
            </div>
          )}
        </div>
      </>
    );
  }

  renderFileDropArea(isOverlay) {
    const selectedFile = this.state.selectedFile;
    const globalDragActive = this.state.globalDragActive;
    const dashedBorder =
      '2px dashed ' + (globalDragActive ? '#c0d36b' : '#cdd1c5');
    return (
      <div className="file-upload-panel" style={{ width: '100%' }}>
        <div
          style={{
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            gap: '16px',
            width: '100%',
          }}
        >
          <div
            style={{
              width: '100%',
              minHeight: '180px',
              border: dashedBorder,
              borderRadius: '4px',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              background: globalDragActive ? '#f9fff2' : '#ffffff',
            }}
            onDragOver={this.handleDragOver}
            onDrop={(e) => {
              e.stopPropagation();
              this.handleDrop(e);
            }}
          >
            {selectedFile ? (
              <div
                style={{
                  display: 'flex',
                  flexDirection: 'row',
                  alignItems: 'center',
                  justifyContent: 'space-between',
                  gap: '12px',
                  width: '90%',
                  color: '#6b6b6b',
                }}
              >
                <div
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    gap: '12px',
                  }}
                >
                  <FontAwesomeIcon icon={['fas', 'file']} />
                  <div>
                    <div>Selected file:</div>
                    <div>{selectedFile.name}</div>
                  </div>
                </div>
                <span
                  className="map-menu-icon esri-icon-close"
                  onClick={this.clearSelectedFile}
                  onKeyDown={this.clearSelectedFile}
                  tabIndex="0"
                  role="button"
                ></span>
              </div>
            ) : (
              <div
                style={{
                  display: 'flex',
                  flexDirection: 'column',
                  alignItems: 'center',
                  gap: '12px',
                  color: '#6b6b6b',
                  textAlign: 'center',
                }}
              >
                <div>
                  Drag and drop
                  <br />
                  or browse your PC
                </div>
                <div
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    gap: '8px',
                  }}
                >
                  <FontAwesomeIcon icon={['fas', 'file']} />
                  <span>.zip</span>
                </div>
              </div>
            )}
          </div>
          {selectedFile ? (
            <button
              className="esri-button"
              disabled={!selectedFile}
              style={{
                width: '100%',
              }}
              onClick={this.handleAddClick}
            >
              Add
            </button>
          ) : (
            <button
              className="esri-button"
              disabled={false}
              style={{
                width: '100%',
              }}
              onClick={this.handleBrowseClick}
            >
              Browse
            </button>
          )}
        </div>
      </div>
    );
  }

  handleDragOver(e) {
    e.preventDefault();
  }

  handleDrop(e) {
    e.preventDefault();
    const file =
      e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files[0];
    if (!file) return;
    this.processInputPayload(file);
  }

  handleAddClick() {
    const file = this.state.selectedFile;
    if (!file) return;
    const inputError = this.resolveInputError(file);
    if (inputError) {
      this.setState({
        showInfoPopup: true,
        infoPopupType: inputError,
        selectedFile: null,
        globalDragActive: false,
      });
      if (typeof this.uploadFileErrorHandler === 'function') {
        this.uploadFileErrorHandler(inputError);
      }
      if (this.fileInput && this.fileInput.current) {
        this.fileInput.current.value = null;
      }
      return;
    }
    try {
      this.uploadUrlServiceHandler(file, 'FILE');
    } catch (err) {
      this.errorPopup();
      if (typeof this.uploadFileErrorHandler === 'function') {
        this.uploadFileErrorHandler();
      }
    } finally {
      this.setState({ selectedFile: null, globalDragActive: false });
      if (this.fileInput && this.fileInput.current) {
        this.fileInput.current.value = null;
      }
    }
  }

  clearSelectedFile() {
    this.setState({ selectedFile: null, globalDragActive: false });
    if (this.fileInput && this.fileInput.current) {
      this.fileInput.current.value = null;
    }
  }
}
export default UploadWidget;
