const fs = require("fs");
const config = require("../config");
const hapi = require("../hapi");
const path = require("path");
const {omit} = require("lodash")

const ENTITY = "uikit";

const { read, write} = config.host(ENTITY);

const standardEntity = require("../standardEntity");

const updateUikitEntity = async (
  api,
  { entity, location}
) => {
  const config = read(api.host, location)
  const entityData = config[entity.toLowerCase()];
  const entityContent = fs.readFileSync(
    path.resolve(location, "src", entityData.src)
  ).toString();

  const response = await api[`uikit${entity}`].update({
    id: entityData.id,
    data: JSON.parse(entityContent),
    __v: entityData.__v
  });

  const toSaveData = {
    [entity.toLowerCase()]: {
      ...entityData,
      __v: response.data.__v
    }
  };

  write(api.host, {...config, ...toSaveData}, location)
  

  
  return { response, toSaveData };
};

const init = async (
  api,
  { palette, typography, buttons, location = process.cwd() }
) => {
  const config = read(api.host, location);
  if (config) throw "exists";

  try {
    const paletteData = fs.readFileSync(path.resolve(location, "src", palette));
    const typographyData = fs.readFileSync(
      path.resolve(location, "src", typography)
    );
    const buttonData = fs.readFileSync(path.resolve(location, "src", buttons));

    const {data: {_id: paletteId, __v: paletteVersion}} = await api.uikitPalette.add({data: JSON.parse(paletteData)})
    const {data: {_id: typographyId, __v: typographyVersion}} = await api.uikitTypography.add({data: JSON.parse(typographyData)})
    const {data: {_id: buttonId, __v: buttonVersion}} = await api.uikitButton.add({data: JSON.parse(buttonData)})

    const toSave = {
      palette: { id: paletteId, src: palette, __v: paletteVersion },
      typography: { id: typographyId, src: typography, __v: typographyVersion },
      button: { id: buttonId, src: buttons, __v: buttonVersion },
    };

    write(api.host, toSave, location);

    return toSave
  } catch (error) {
    throw new Error(error);
  }
};

const commit = async (
  api,
  { location = process.cwd() }
) => {
  const config = read(api.host, location);
  const result = {};

  try {
    const { response } = await updateUikitEntity(api, {
      entity: "Palette",
      location,
      config
    });
    result.palette = response;
  } catch (e) {
    throw new Error('cannot commit palette for the uikit')
  }


  try {
    const { response } = await updateUikitEntity(api, {
      entity: "Button",
      location,
      config
    });
    result.button = response;
  } catch (e) {
    throw new Error('cannot commit buttons for the uikit')
  }

  try {
    const { response } = await updateUikitEntity(api, {
      entity: "Typography",
      location,
      config
    });
    result.typography = response;

  } catch (e) {
    throw new Error('cannot commit typography for the uikit')
  }

  return result;
};



const createTemplateByUIKit = async (api, { location = process.cwd(), name}) => {
  const config = read(api.host, location);

  const uikitPalette = config.palette.id
  const uikitButton = config.button.id
  const uikitTypography = config.typography.id


  const {data: {_id, __v}} = await api.website.add({
    data: {
      name,
      uikitPalette,
      uikitButton,
      uikitTypography,
      editorVersion: 2,
      roles: ["template"]
    }
  })

  write(api.host, {...config, template: {id: _id, __v}}, location);


  const {data} = await api.website.publishAsTemplate({id: _id, data: {name}});

  return data;
};

const unpublishTemplate = async (api, { location = process.cwd()}) => {
  const config = read(api.host, location);
  const templateId = config.templateId;

  const { data } = await api.website.unpublishAsTemplate({id: templateId});
  write(api.host, omit(config, 'template'), location);

  return data;
};

const purgeTemplate = async (api, { location = process.cwd() , id}) => {
  const config = read(api.host, location);
  id = id || (config.template || config.template.id)
  if (!id) throw "uikit doesnt have template";
  // unlink(api.host, location);
  //unpublish
  const { data } = await api.website.remove({id});
  write(api.host, omit(config, 'template'), location);

  return data;
};

module.exports = yargs => yargs.command({
  command: "uikit",
  desc: "uikit support",
  handler: () => yargs.showHelp(),
  builder: yargs => yargs.command({
    command: "palette",
    desc: "Palette list/get/update/remove",
    builder: standardEntity("uikitPalette"),
    handler: () => yargs.showHelp(),
  }).command({
    command: "typography",
    desc: "Typography list/get/update/remove",
    builder: standardEntity("uikitTypography"),
    handler: () => yargs.showHelp(),
  }).command({
    command: "button",
    desc: "Button list/get/update/remove",
    builder: standardEntity("uikitButton"),
    handler: () => yargs.showHelp(),
  }).command({
    command: "init",
    desc: "init uikit",
    builder: yargs =>  yargs
      .option("name", { desc: "Uikit name", string: true })
      .option("palette", {
        default: "palette.json",
        desc: "palette entry point",
        demand: "please, specify --palette",
        string: true
      }).option("typography", {
        default: "typography.json",
        desc: "typography entry point",
        demand: "please, specify --typography",
        string: true
      }).option("buttons", {
        default: "buttons.json",
        desc: "buttons entry point",
        demand: "please, specify --buttons",
        string: true
      }).usage(
        '$0 uikit init --name="My UiKit" --palette=./palette.json --typography=./typography.json --buttons=./buttons.json'
      ),
    handler: hapi(init)
  }).command({
    command: "commit",
    desc: "Commit changes",
    builder: yargs =>
      yargs
        .option("name", { desc: "UIKit name", string: true }),
    handler: hapi(commit)
  }).command({
    builder: yargs =>
      yargs
        .option("name", { desc: "UIKit name", string: true }),
    command: "createTemplateByUIKit",
    desc: "Make UIKit as template",
    handler: hapi(createTemplateByUIKit)
  }).command({
    command: "unpublishUikitTemplate",
    desc: "Unpublish uikit template",
    handler: hapi(unpublishTemplate)
  }).command({
    builder: yargs =>
      yargs
        .option("id", { desc: "UIKit id", string: true }),
    command: "purgeTemplate",
    desc: "Purge uikit template",
    handler: hapi(purgeTemplate)
  })
})
