import { CQStyleGroups } from "./styles";

const jcrPrimaryType = { "jcr:primaryType": "nt:unstructured" };

export type ComponentPolicyType = {
  "component": string;
  "description": string;
  "title": string;
  "policy": string;
  "styles"?: CQStyleGroups;
  "attributes"?: object;
  "configurations"?: object;
}
export class ComponentPolicy {
  "component": string;
  "description": string;
  "title": string;
  "policy": string;
  "styles"?: CQStyleGroups;
  "attributes"?: object;
  "configurations"?: object;

  constructor(settings: ComponentPolicyType) {
    this.policy = settings?.policy;
    this.title = settings?.title;
    this.description = settings?.description || null;
    this.styles = settings?.styles || null;
    this.component = settings?.component;
    this.attributes = settings?.attributes;
    this.configurations = settings?.configurations;
  }

  format(includeResourceType: boolean = true, theme?: object) {
    const policy = {
      [this.policy]: {
        attributes: { 
          ...jcrPrimaryType,
          "sling:resourceType": "wcm/core/components/policy/policy",
          "jcr:title": this.title,
          "jcr:description": this.description,
          ...this.formatAttributes(), 
        },
        "jcr:content": {
          attributes: jcrPrimaryType,
        },
        ...this.formatStyleGroups(theme),
        ...this.formatConfigurations(this.configurations),
      }
    }

    if (includeResourceType) return { [this.component]: policy };
    else return policy;
  }

  private formatAttributes() {
    for (let key in this.attributes) {
      let value: any | any[] = this.attributes[key];
      switch (typeof this.attributes[key]) {
        case "object":
          if (Array.isArray(this.attributes[key])) {
            this.attributes[key] = `[${value.join(",")}]`;
          } 
          break;
        default: 
          this.attributes[key] = value.toString();
          break;
      }
    }

    return this.attributes;
  }

  private formatStyleGroups(theme?) {
    if (this.styles === null) return false;
    return {
      "cq:styleGroups": {
        attributes: jcrPrimaryType,
        ...this.styles.format("xml", theme),
      }
    }
  }

  private formatConfigurations(configuration: object) {
    for (let key in configuration) {
      if (typeof configuration[key] === "object" && key !== "attributes") {
        if (configuration[key].attributes) {
          if (!configuration[key].attributes["jcr:primaryType"]) {
            configuration[key].attributes["jcr:primaryType"] = "nt:unstructured";
          }
        } else {
          configuration[key].attributes = { "jcr:primaryType": "nt:unstructured" };
        }
        this.formatConfigurations(configuration[key]);
      }
    }
    return configuration;
  }
}