import { uCursor } from "./shortcuts/entities";
import { brackets } from "./shortcuts/selectors";
import { append } from "./shortcuts/transformers";

export interface Root {
  className: string;
  extends?: string;
  props: Prop[];
  methods: Method[];
  info?: {
    version: string;
  };
}

export interface Prop {
  name: string;
  type?: string;
}

export interface Method {
  name: string;
  type: string;
  params: Param[];
}

export interface Param {
  name: string;
  type: string;
}

const data: Root = {
  className: "Person",
  extends: "Human",
  info: {
    version: "1.0.0",
  },
  props: [
    {
      name: "name",
      type: "string",
    },
    {
      name: "age",
      type: "string",
    },
    { name: "gender", type: "Gender" },
  ],
  methods: [
    {
      name: "fromJson",
      type: "Person",
      params: [
        {
          name: "json",
          type: "any",
        },
      ],
    },
    {
      name: "concat",
      type: "string",
      params: [
        {
          name: "a",
          type: "string",
        },
        {
          name: "b",
          type: "string",
        },
      ],
    },
  ],
};

const cursor = uCursor<Root>()
  .prefix("export class ")
  .block(" {", "}")
  .ident({
    char: " ",
    size: 2,
  })
  .writeFrom("className", (name) => name)
  .writeFrom("extends", (name) => (name ? ` extends ${name}` : ""))
  .in("info", (info) =>
    info.writeFrom("version", (version) => `// Version: ${version}\n\n`)
  )
  .each("props", (prop) =>
    prop
      .write(({ name, type }) => `${name}: ${type};`)
      .join("\n")
      .clean()
  )
  .linebreak()
  .each("props", (propsCursor) =>
    propsCursor
      .prefix("props: [")
      .write((prop) => `"${prop.name}"`)
      .join(", ")
      .suffix("],\n")
  )
  .linebreak(2)
  .expand((expandedCursor) =>
    expandedCursor
      .write(() => "utils: ")
      .block("{", "}")
      .each("methods", (method) =>
        method
          .writeFrom("name", (name) => name + "(")
          .writeFromEach(
            "params",
            ({ name, type }, _, { isLast }) =>
              `${name}: ${type}${!isLast ? ", " : ""}`
          )
          .write(() => ")")
          .writeFrom("type", (type) => ": " + type + " ")
          .block("{", "}")
          .join("\n\n")
      )
      .prefix("// Start Util\n")
      .suffix("\n// End Util")
  );

console.log(cursor.render(data));
