// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-glyph: cloud-download-alt; icon-color: deep-gray; share-sheet-inputs: file-url,url,plain-text;
/**
 * @version 1.1.1
 * @author Honye
 */

/**
 * @param {object} options
 * @param {string} [options.title]
 * @param {string} [options.message]
 * @param {Array<{ title: string; [key: string]: any }>} options.options
 * @param {boolean} [options.showCancel = true]
 * @param {string} [options.cancelText = 'Cancel']
 */
async function presentSheet (options) {
  options = {
    showCancel: true,
    cancelText: 'Cancel',
    ...options
  };
  const alert = new Alert();
  if (options.title) {
    alert.title = options.title;
  }
  if (options.message) {
    alert.message = options.message;
  }
  if (!options.options) {
    throw new Error('The "options" property of the parameter cannot be empty')
  }
  for (const option of options.options) {
    alert.addAction(option.title);
  }
  if (options.showCancel) {
    alert.addCancelAction(options.cancelText);
  }
  const value = await alert.presentSheet();
  return {
    value,
    option: options.options[value]
  }
}

/**
 * @param {{[language: string]: string} | string[]} langs
 */
const i18n = (langs) => {
  const language = Device.language();
  if (Array.isArray(langs)) {
    langs = {
      en: langs[0],
      zh: langs[1],
      others: langs[0]
    };
  } else {
    langs.others = langs.others || langs.en;
  }
  return langs[language] || langs.others
};

const filePath = module.filename;
const appRoot = filePath.substring(0, filePath.lastIndexOf('/'));
const iCloudManager = FileManager.iCloud();
const fs = iCloudManager.isFileStoredIniCloud(filePath) ? iCloudManager : FileManager.local();

const main = async () => {
  if (config.runsInApp) {
    const params = args.queryParameters;
    const scriptURL = params && params.url;
    if (scriptURL) {
      installByURL(scriptURL);
      return
    }

    const { value } = await presentSheet({
      message: i18n([
        'Where does the code come form? \n☞ Notice Development will override local file!',
        '代码从哪里来?\n☞注意开发服会覆盖本地文件!'
      ]),
      options: [
        { title: i18n(['Clipborad', '剪贴板的链接']) },
        { title: i18n(['Development', '开发服']) }
      ],
      cancelText: i18n(['Cancel', '取消'])
    });
    switch (value) {
      /** Development */
      case 1: {
        const alert = new Alert();
        alert.title = i18n(['Development', '开发服']);
        alert.message = i18n([
          'The file will be overwritten if it exists!',
          '如果文件已存在将会被覆盖!'
        ]);
        const host = (Keychain.contains('dev-host') && Keychain.get('dev-host')) || '';
        const port = (Keychain.contains('dev-port') && Keychain.get('dev-port')) || '';
        const name = (Keychain.contains('dev-name') && Keychain.get('dev-name')) || '';
        alert.addTextField('host', host);
        alert.addTextField('port', port);
        alert.addTextField(
          i18n(['name', '文件名']),
          name
        );
        alert.addAction(i18n(['Download', '下载']));
        alert.addCancelAction(i18n(['Cancel', '取消']));
        const number = await alert.present();
        /** Download */
        if (number === 0) {
          const host = alert.textFieldValue(0);
          const port = alert.textFieldValue(1);
          const name = alert.textFieldValue(2);
          Keychain.set('dev-host', host);
          Keychain.set('dev-port', port);
          Keychain.set('dev-name', name);
          installByURL(
            `http://${host}:${port}/${encodeURIComponent(name)}.js`,
            { override: true }
          );
        }
        break
      }
    }
  }

  const urls = args.urls;
  if (urls && urls.length) {
    for (const url of urls) {
      installByURL(url);
    }
  }
};

/**
 * download and install script from the url
 *
 * @param {string} url url of the script
 * @param {object} options
 * @param {boolean} [options.override] weather override the existed file
 */
async function installByURL (url, options) {
  const { override } = {
    override: false,
    ...options
  };

  const blobRegxp = /^https:\/\/github\.com\/(.+)\/blob\/(.+\.js$)/;
  if (blobRegxp.test(url)) {
    url = url.replace(blobRegxp, 'https://raw.githubusercontent.com/$1/$2');
  }

  const request = new Request(url);
  const text = await request.loadString()
    .catch(async (e) => {
      console.error(e);
      const notification = new Notification();
      notification.title = Script.name();
      notification.body = e.toString();
      await notification.schedule();
      throw e
    });
  const fileName = decodeURIComponent(url.split('/').pop().replace(/([^?#]+)([?#].*)*/, '$1'));
  let filePath = `${appRoot}/${fileName}`;
  if (fs.fileExists(filePath) && !override) {
    const alert = new Alert();
    alert.message = i18n([
      `${fileName} existed, please rename`,
      `${fileName} 已存在,请重命名`
    ]);
    alert.addTextField(
      i18n(['new file name', '新文件名']),
      fs.fileName(filePath) + '1'
    );
    alert.addAction(i18n(['Save', '保存']));
    alert.addCancelAction(i18n(['Cancel', '取消']));
    const num = await alert.present();
    if (num === -1) return
    const newName = alert.textFieldValue(0);
    if (newName) {
      filePath = `${appRoot}/${newName}.js`;
    } else {
      return
    }
  }
  fs.writeString(filePath, text);
  await genAlert(i18n([
    `${fileName} installed success`,
    `${fileName} 安装成功`
  ]));
}

async function genAlert (message) {
  const _alert = new Alert();
  _alert.message = message;
  return _alert.presentAlert()
}

await main();