import { Model } from '../../common';
import Component from '../../dom_components/model/Component';
import EditorModel from '../../editor/model/Editor';

export type HTMLGeneratorBuildOptions = {
  /**
   * Remove unnecessary IDs (eg. those created automatically).
   */
  cleanId?: boolean;

  /**
   * You can pass an object of custom attributes to replace with the current ones
   * or you can even pass a function to generate attributes dynamically.
   */
  attributes?: Record<string, any> | ((component: Component, attr: Record<string, any>) => Record<string, any>);
};

export default class HTMLGenerator extends Model {
  build(model: Component, opts: HTMLGeneratorBuildOptions & { em?: EditorModel } = {}) {
    const { em, ...restOpts } = opts;
    const htmlOpts = restOpts;

    // Remove unnecessary IDs
    if (opts.cleanId && em) {
      const rules = em.Css.getAll();
      const idRules = rules
        .toJSON()
        .map((rule: any) => {
          const sels = rule.selectors;
          const sel = sels && sels.length === 1 && sels.models[0];
          return sel && sel.isId() && sel.get('name');
        })
        .filter(Boolean);

      if (!htmlOpts.attributes) {
        htmlOpts.attributes = (mod, attrs) => {
          const { id } = attrs;
          if (
            id &&
            id[0] === 'i' && // all autogenerated IDs start with 'i'
            !mod.get('script') && // if the component has script, we have to leave the ID
            !mod.get('attributes')!.id && // id is not intentionally in attributes
            idRules.indexOf(id) < 0 // we shouldn't have any rule with this ID
          ) {
            delete attrs.id;
          }
          return attrs;
        };
      }
    }

    return model.toHTML(htmlOpts);
  }
}
