'use strict';

import gulp from 'gulp';
import notify from 'gulp-notify';
import fs from 'node:fs/promises'; // Using the promise-based fs API.
import svgSprite from 'gulp-svg-sprite';

import { config } from '../config.mjs';

const iconsSpriteClasses = async (callback) => {
  try {
    // Dynamically import imagemin and its plugins.
    const imageminModule = await import('gulp-imagemin');
    // gulp-imagemin often has a default export for the main function.
    const imagemin = imageminModule.default;
    // Optimizers like mozjpeg, optipng, svgo are often named exports.
    const { svgo } = imageminModule;

    return gulp.src(config.sprite.src)
      .pipe(svgSprite({
        shape: {
          spacing: {
            padding: [0, 10, 10, 10],
            box: 'content',
          },
          dimension: {
            maxWidth: 16,
            maxHeight: 16,
            precision: 2,
          },
          id: {
            separator: '--',
            generator: "rs-icon--%s",
          },
        },
        mode: {
          css: {
            dest: './',
            layout: 'diagonal',
            sprite: config.sprite.svg_css,
            bust: false,
            render: {
              scss: {
                dest: config.sprite.css2,
                template: config.sprite.template2,
              },
            },
          },
        },
        svg: {
          xmlDeclaration: true,
          doctypeDeclaration: true,
          namespaceIDs: true,
          namespaceIDPrefix: 'rs-',
          namespaceClassnames: true,
          dimensionAttributes: true,
        },
        variables: {
          mapname: 'icons',
        },
      }))
      .pipe(imagemin([
        svgo(
          { removeUselessDefs: false },
          { cleanupIDs: false },
          { removeXMLNS: false },
          { removeViewBox: false },
          { removeComments: true },
        )
      ]))
      .pipe(gulp.dest('./'));
  } catch (err) {
    notify(err);
    throw err; // Re-throw the error to signal task failure
  }
};

const _iconsSprite = async (callback) => {
  try {
    // Dynamically import imagemin and its plugins.
    const imageminModule = await import('gulp-imagemin');
    // gulp-imagemin often has a default export for the main function.
    const imagemin = imageminModule.default;
    // Optimizers like mozjpeg, optipng, svgo are often named exports.
    const { svgo } = imageminModule;

    return gulp.src(config.sprite.src)
      .pipe(svgSprite({
        shape: {
          spacing: {
            padding: [0, 0, 0, 0],
            box: 'content',
          },
          dimension: {
            maxWidth: 16,
            maxHeight: 16,
            precision: 2,
          },
          id: {
            separator: '--',
            generator: "rs-icon--%s",
          },
        },
        mode: {
          css: {
            dest: './',
            layout: 'diagonal',
            sprite: config.sprite.svg,
            bust: false,
            render: {
              scss: {
                dest: config.sprite.css,
                template: config.sprite.template,
              },
            },
          },
          symbol: {
            dest: './',
            sprite: config.sprite.svg_inline,
            inline: true,
          },
        },
        svg: {
          namespaceIDs: true,
          namespaceIDPrefix: 'rs-',
        },
        variables: {
          mapname: 'icons',
        }
      }))
      .pipe(imagemin([
        svgo(
          {
            plugins: [
              { name: 'removeDimensions', active: false },
              { name: 'removeViewBox', active: false },
              { name: 'cleanupIDs', active: false },
              { name: 'removeXMLNS', active: false },
              { name: 'removeUselessDefs', active: false },
              { name: 'removeComments', active: true },
              { name: 'removeDoctype', active: true },
              { name: 'removeXMLProcInst', active: true },
            ]
          }
        )
      ]))
      .pipe(gulp.dest('./'));
  } catch (err) {
    notify(err);
  }
};

function toTitleCase(str) {
  return str.replace(
    /\w\S*/g,
    function (txt) {
      return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
    }
  );
}

const listIcons = async (callback) => {
  try {
    const files = await fs.readdir(config.sprite.src_folder);

    // Initialize an empty array to hold our icon data
    const icon_data = {};

    for (const file of files) {
      if (file.endsWith('.svg')) {
        const name = file.split('.svg')[0];

        console.log(`- ${name}`); // Still useful for logging progress

        // Add an object for each icon to our array
        icon_data[name] = "";
      }
    }

    // Convert the JavaScript array to a JSON string
    // The 2 provides pretty-printing (indentation) for readability
    const json_output = JSON.stringify(icon_data, null, 2);

    // Write the JSON output to the path specified in config.sprite.icon_list
    // which you have now updated to point to a .json file
    await fs.writeFile(config.sprite.icon_list, json_output);

  } catch (err) {
    console.error('Error listing icons:', err);
    // Call the callback with an error to signal Gulp task failure
    if (callback) callback(err);
    else throw err; // Re-throw if no callback provided (e.g., direct script execution)
  }
  // Call the callback to signal Gulp task completion (if no error)
  if (callback) callback();
};

const fixSVG = async (callback) => {
  try {
    const data = await fs.readFile(config.sprite.svg_inline, 'utf8');

    notify('find fill and stroke colors (that are not none or currentColor).');
    const rePattern = new RegExp("(?<=fill=\")(?!none|currentColor)(.*?)(?=\")", 'g');
    const rePattern2 = new RegExp("(?<=stroke=\")(?!none|currentColor)(.*?)(?=\")", 'g');
    const rePattern3 = new RegExp("\"", 'g');

    notify('replace fill and stroke colors with currentColor so it can be changed via CSS.');
    let newData = data.replace(rePattern, 'currentColor');
    newData = newData.replace(rePattern2, 'currentColor');
    newData = newData.replace(rePattern3, '\'');

    await fs.writeFile(config.sprite.svg_inline, newData);
  } catch (err) {
    notify(err);
    throw err; // Re-throw the error to signal task failure.
  }
};

/**
 * This task generates a sprite and puts it in images.
 */
export const iconsSpriteSpriteTask = _iconsSprite;
export const iconsSpriteCleanupTask = fixSVG;
export const iconsSpriteTask = gulp.series(
  async (cb) => listIcons(cb),
  async (cb) => iconsSpriteClasses(cb),
  async (cb) => iconsSpriteSpriteTask(cb),
  async (cb) => iconsSpriteCleanupTask(cb),

);

export const iconsSprite = iconsSpriteTask;
