const {read} = require('../config').host("block");
const ref2url = require("../ref");
const fetch = require("node-fetch");
const fs = require("fs");
// const executeServer = require("./executeServer")

// const notify = data => executeServer.notify && executeServer.notify(data);

const load = ref => fetch(ref2url(ref)).then($ => $.text())

module.exports = async function(api, argv) {
  const {id} = argv;
  const buildBlock = require("./build");
  const location = process.cwd()
  let js, css, content, block;

  const Logger = require("../Logger");
  const log = Logger(argv)
  const config = read(api.host);
  if(!config) throw "config is not found";

  async function _getBlock() {
    const _id = id || (block && block._id) || config.id
    block = await api.block.get({id: _id});
    if(!block || !block.data) throw "Block is not found"
    return (block = block.data);
  }

  await _getBlock();
  if(id) {
    const {contentRef, src = {}} = block;
    if(!src.js) throw "the block has no src"
    js = src.js;
    css = src.css;
    contentRef && (content = await load(contentRef));
  } else {
    // js = fs.readFileSync(config.entrypoint).toString("utf8");
    // css = config.style && fs.readFileSync(config.style).toString("utf8") || "";
  }
  const remote = !!id;
  const compile = async ({js, css}) => ({...block, view: await buildBlock(location), js, css, content, remote});
  const getBlock = () => compile({js, css});
  async function commit({js, css, content, modifier}) {
    const view = await buildBlock(location);
    await _getBlock();
    block.content = content;
    block.src = {js, css};
    block.view = view;
    block.modifier = modifier;
    await api.block.update({id: block._id, __v: block.__v, block});
    if(!id) {
      fs.writeFileSync(config.entrypoint, js);
      config.style && fs.writeFileSync(config.style, css);
    }

    await _getBlock();
    return {...block, view, js, css, content, remote}
  }

  async function save({js, css, content, modifier}) {
    if(id) throw "its remote block"
    const view = await buildBlock(location)
    await _getBlock();
    block.content = content;
    block.src = {js, css};
    block.view = view;
    block.modifier = modifier;
    fs.writeFileSync(config.entrypoint, js);
    config.style && fs.writeFileSync(config.style, css);
    return {...block, view, js, css, content, remote}
  }

  const publish = () => api.block.publish({id: block._id});
  const unpublish = () => api.block.unpublish({id: block._id});
  const resourceList = ({ownerId}) => api.block.listResources({ownerId})
  const resourceRemove = ({ownerId, id}) => api.block.removeResource({ownerId, id})

  const getHost = () => api.host
  const getToken = () => api.socket.token()

  // function onEntrypointChanged() {
  //   console.log("onEntrypointChanged")
  //   if(Date.now() - saving > 100) return;
  //   js = fs.readFileSync(config.entrypoint).toString("utf8")
  //   getBlock().then(notify)
  // }
  // function onStyleChanged() {
  //   if(saving - Date.now() > 100) return;
  //   css = fs.readFileSync(config.style).toString("utf8") || "";
  //   getBlock().then(notify)
  // }
  // if(!id) {
  //   fs.watch(config.entrypoint, onEntrypointChanged);
  //   config.style && fs.watch(config.style, onStyleChanged);
  // }

  await require("./executeServer")({api, log, actions: {getBlock, compile, save, commit, publish, unpublish, resourceList, resourceRemove, getHost, getToken}});
  // if(!id) {
  //   fs.unwatch(config.entrypoint, onEntrypointChanged);
  //   config.style && fs.unwatch(config.style, onStyleChanged);
  // }
}
