const { Telegraf } = require('telegraf')
const DOMPurify = require('dompurify')
const { JSDOM } = require('jsdom')
const { window } = new JSDOM('<!DOCTYPE html>')
const domPurify = DOMPurify(window)

const DEFAULT_IMG_URL = "https://gancio.org/assets/gancio.png"

const plugin = {
  configuration: {
    name: 'Telegram',
    author: 'fadelkon',
    url: 'https://framagit.org/bcn.convocala/gancio-plugin-telegram-bridge',
    description: 'Republishes content to Telegram channels or groups. The goal is to spread the info of our networks to the capitalist cyberspace, and pull otherwise isolated people to our radical and free part of the internet.',
    settings: {
      auth_token: {
        type: 'TEXT',
        description: 'Auth token',
        required: true,
        hint: 'Your Telegram\'s <strong>bot token</strong> you want to impersonate.<br/><a href="https://core.telegram.org/bots#6-botfather">Help on telegram bots</a>'
      },
      chat_id: {
        type: 'TEXT',
        description: 'Channel id',
        required: true,
        hint: 'The <strong>channel/group id</strong> where to publish the messages.<br/><a href="https://github.com/GabrielRF/telegram-id">Help on getting chat ids</a>'
      }
    }
  },
  gancio: null, // { helpers, log, settings }
  log: null,
  bot: null,
  settings: null,

  load(gancio, settings) {
    plugin.gancio = gancio
    plugin.log = gancio.log
    plugin.settings = settings


    plugin.bot = new Telegraf(settings.auth_token)
    plugin.log.info("Telegram plugin loaded!")
  },

  onTest() {
      plugin.log.debug("Send test message to Telegram")
      let image_url = DEFAULT_IMG_URL;
      let html_msg = '<b>GANCIO TELEGRAM PLUGIN TEST</b>\n\n' +
      'It\'s <i>working</i>! This means that the supplied <code>chat id</code> and the <code>bot key</code> are correct\n\n' +
      'However, if event messages are not sent, make sure that your gancio is serving from a public URL.\n' +
      'If it is not, then telegram won\'t be able to fetch your images and so will fail with a "bad url" error.\n\n' +
      'If it is but still messages are not sent, it may be due to a violation of Telegram\'s API rules, such as message size.\n' +
      'If that\'s the case, please, report it to the plugin development team at https://framagit.org/bcn.convocala/gancio-plugin-telegram-bridge/'
      plugin.bot.telegram.sendPhoto(
        plugin.settings.chat_id, image_url, { "parse_mode": "HTML", "caption": html_msg }
      ).then(logOk, logErr)
  },

  onEventCreate(event) {
    plugin.log.debug("Send new event to Telegram")
    if (event.is_visible) {
      let image_url = `${plugin.gancio.settings.baseurl}/logo.png`;
      if (event.media && event.media.length) {
        image_url = `${plugin.gancio.settings.baseurl}/media/${event.media[0].url}`
      }
      if (image_url.includes("localhost")) {
          plugin.log.warn("Replacing media with gancio's logo, as telegram won't be able to fetch an image hosted in a private URL")
          image_url = DEFAULT_IMG_URL
      }
      plugin.bot.telegram.sendPhoto(
        plugin.settings.chat_id,
        image_url,
        { "parse_mode": "HTML", "caption": renderEvent(event) }
      ).then(logOk, logErr)
    }
  },

  onEventUpdate(event) {
    plugin.log.info(`Event "${event.title}" updated`)
    plugin.log.debug(event)
  },

  onEventDelete(event) {
    plugin.log.info(`Event "${event.title}" deleted`)
    plugin.log.debug(event)
  }
}

function logOk(data) {
    plugin.log.debug("Telegram message sent successfully: " + JSON.stringify(data))
}

function logErr(data){
    plugin.log.error("Telegram message not sent because some error happened: " + JSON.stringify(data))
}

// Telegram only allows a few html html tags, just for very basic formatting and code
function cleanHtml(html) {
    // save some formatting (line breaks, lists)
    html = html
        .replace(/\n/g, "")
        .replace(/<p>/g, "")
        .replace(/<\/p>/g, "\n")
        .replace(/<br ?\/?>/g, "\n")
        .replace(/<li>/g, "  • ")
    // call gancio's sanitize to get a standard clean, with its hooks
    html = plugin.gancio.helpers.sanitizeHTML(html);
    // call sanitize again, but with telgram's reduced allowed tags
    return domPurify.sanitize(html, {
      ALLOWED_TAGS: ['a', 'i', 'b', 'code', 'pre', 'u', 's'],
      ALLOWED_ATTR: ['href', 'language']
    })
}

function renderPlace(place) {
    if (place.longitude && place.latitude) {
        return `<a href="https://www.openstreetmap.org/?mlat=${place.latitude}&mlon=${place.longitude}#map=19/${place.latitude}/${place.longitude}">${place.name}</a>`
    } else {
       return `${place.name}`
    }
}

function renderEvent(event) {
  return `\
<b>${event.title}</b>
${event.description? "\n" + cleanHtml(event.description) + '\n' : ""}
📅 ${(new Date(event.start_datetime * 1000)).toLocaleDateString()} ⏰ ${(new Date(event.start_datetime * 1000)).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}
📌 ${renderPlace(event.place)}
${event.tags.reduce((x, y) => { return x + " #" + y.tag.replaceAll(" ", "_") }, "").trim()}
<a href="${plugin.gancio.settings.baseurl}">${plugin.gancio.settings.title}</a>
`
}

module.exports = plugin
