import { MODULE_ID } from './constants.js';

const FILTERED_FILE_LABEL_KEYWORDS = ['bw', 'terrain', 'tileable'];

export class ImagePicker extends foundry.applications.api.HandlebarsApplicationMixin(
  foundry.applications.api.ApplicationV2
) {
  /**
   * @param {Array[Preset]} presets
   */
  constructor(callback, terrainPaths) {
    super({});
    this._terrainPaths = terrainPaths;
    this._callback = callback;
  }

  static DEFAULT_OPTIONS = {
    id: 'terrain-image-picker',
    tag: 'form',
    form: {
      handler: undefined,
      submitOnChange: false,
      closeOnSubmit: false,
    },
    window: {
      contentClasses: ['standard-form'],
      title: 'Change Terrain',
      resizable: true,
    },
    position: {
      width: 600,
      height: 600,
    },
    actions: {
      clickImage: ImagePicker._onClickImage,
      select: ImagePicker._onSelect,
      cancel: ImagePicker._onCancel,
    },
  };

  /**
   * Handles image clicks
   * @param {PointerEvent} event
   * @param {HTMLElement} target
   */
  static _onClickImage(event, target) {
    this.element.querySelectorAll('.image-container img').forEach((img) => img.classList.remove('selected'));
    target.classList.add('selected');
    this._selectedImage = target.dataset.src;

    this.element.querySelector('button[data-action="select"]').removeAttribute('disabled');
  }

  /**
   * Handles 'Select' button click
   * @param {PointerEvent} event
   * @param {HTMLElement} target
   */
  static _onSelect(event, target) {
    this._callback?.(this._selectedImage);
    this.close();
  }

  /**
   * Handles 'Cancel' button click
   * @param {PointerEvent} event
   * @param {HTMLElement} target
   */
  static _onCancel(event, target) {
    this._callback?.(null);
    this.close();
  }

  /** @override */
  static PARTS = {
    main: { template: `modules/${MODULE_ID}/templates/ImagePicker.hbs` },
  };

  /** @override */
  async _prepareContext(options) {
    const context = await super._prepareContext(options);

    let images = await this._getImages();

    // Process images by pairing up thumbnails with original sources and formatting the file names into labels
    const thumbs = {};
    images = images
      .filter((img) => {
        if (img.includes('_thumb')) {
          thumbs[img.replace('_thumb', '')] = img;
          return false;
        }
        return true;
      })
      .map((img) => {
        return { src: img, thumb: thumbs[img] ?? img, label: this.sourcePathToLabel(img) };
      });

    return Object.assign(context, { images });
  }

  sourcePathToLabel(src) {
    return src
      .split('/')
      .pop()
      .split('.')[0]
      .split(/[ _]+/)
      .map((s) => s.toLocaleLowerCase())
      .filter((s) => !FILTERED_FILE_LABEL_KEYWORDS.includes(s))
      .map((s) => s[0].toLocaleUpperCase() + s.substring(1))
      .join(' ');
  }

  async _getImages() {
    let images = [];
    for (let path of this._terrainPaths) {
      if (!path.includes('*')) {
        images.push(path);
        continue;
      }

      let source = 'data';
      let pattern = path;
      const options = { wildcard: true };

      if (typeof ForgeVTT != 'undefined' && ForgeVTT.usingTheForge) source = 'forgevtt';

      if (/\.s3\./.test(pattern)) {
        source = 's3';
        const { bucket, keyPrefix } = foundry.applications.apps.FilePicker.implementation.parseS3URL(pattern);
        if (bucket) {
          options.bucket = bucket;
          pattern = keyPrefix;
        }
      }

      try {
        const content = await foundry.applications.apps.FilePicker.implementation.browse(source, pattern, options);
        images = images.concat(content.files);
      } catch (e) {}
    }

    return images;
  }
}
