// ==UserScript==
// @name        Bookmark to Cosense
// @namespace   https://scrapbox.io/directory
// @match       *://*/**
// @version     1.1.1
// @author      OKAMURA Naoki aka nyarla <nyarla@kalaclista.com>
// @description The UserScript for bookmark all website to Cosense (formaly known Scrapbox)
// @grant       GM_getValue
// @grant			 GM_registerMenuCommand
// @grant       GM_xmlhttpRequest
// ==/UserScript==

const cosenseId = GM_getValue('COSENSE_ID');

const getProperty = (getters) => {
  for (const getter of getters) {
    const [ selector, access ] = getter;

    const el = document.querySelector(selector);
    const text = el ? access(el) : '';

    if (text) {
      return text;
    }
  }

  return '';
};

const makeCosenseData = () => {
   const content = el => el.getAttribute('content');
   const text    = el => el.textContent;
 
   const title = getProperty([
     // by Open Graph Protocol
     ['meta[property="og:title"]',       content],
     ['meta[name="og:title"]',           content], // this is mistake in website, but supported.
     // by Twitter Card
     ['meta[name="twitter:title"]',      content],
     ['meta[property="twitter:title"]',  content], // that is mistake again in website, but supported.
     // by Microformat v2
     ['.h-entry .p-pname',               text],    // the current microformat is version 2.
     // by Microformat v1
     ['.hentry .entry-title',             text],    // but support microformat version 1 too.
     // by title
     ['title',                           text],    // finally, fallback to getting from title element
   ]).replace(/[\r\n]/g, "");
 
   const summary = getProperty([
     // by Open Graph Protocol
     ['meta[property="og:description"]',       content],
     ['meta[name="og:description"]',           content], // this is mistake in website, but supported.
     // by Twitter card
     ['meta[name="twitter:description"]',      content],
     ['meta[property="twitter:description"]',  content], // this is mistake again in website, but supported.
     // by Microformat v2
     ['.h-entry .p-summary',                   text],    // the current microformat is version 2.
     // by Microformat v1
     ['.hentry .entry-summary',                text],    // but support microformat version 1 too.
     // fallback to meta[name="description"]
     ['meta[name="description"]',              content], // finally, fallback to old style meta[name="description"]
   ]);
 
   const website = getProperty([
     ['meta[property="og:site_name"]',         content], // get website name from og:site_name.
     ['meta[name="og:site_name"]',             content], // this is mistake in website, but supported.
   ]);
 
   const href = getProperty([
     ['meta[property="og:url"]', content],                       // get canonical url from ogp,
     ['meta[name="og:url"]',     content],                       // this is mistake in website, but supported.
     ['link[rel="canonical"]',   el => el.getAttribute('href')], // use rel="canonial" href.
   ]) || location.href;                                          // finally, use location.href.
 
   // get favicon from hidden api by google
   const icon = `https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=${encodeURIComponent(href)}&size=128#.png`;
   const date = new Date().toISOString().split(/T/)[0];
 
   const favicon = `[!<> [${icon}]]`;
   const link    = `[${title} ${href}]`;
 
   const quote   = `> ${summary ? summary : title}\n[> [${decodeURIComponent(href)}]] `;
   const body    =
   `
Date: ${date}

${quote.replace(/\n/g, "\n> ")}

${favicon}
`;
 
 return [title, body];
};

const bookmarkToCosense = () => {
  if (! cosenseId) {
    window.alert('The value of `COSENSE_ID` is not set. Please set `COSENSE_ID` to your UserScript manager');
    return;
  }
   
	const [ title, body ] = makeCosenseData();

	GM_xmlhttpRequest({
   method: 'GET',
   url: `https://scrapbox.io/api/pages/${cosenseId}/${encodeURIComponent(title)}`,
   onload: (res) => {
     const json = JSON.parse(res.responseText);
     if (json.lines.length > 1) {
       location.href = `https://scrapbox.io/${cosenseId}/${encodeURIComponent(title)}`;
       return;
     }

      location.href = `https://scrapbox.io/${cosenseId}/${encodeURIComponent(title)}?body=${encodeURIComponent(body)}`;
    },
  });
 };
 
 const popupCosenseData = () => {
   window.alert(makeCosenseData().join("\n"));
 };
 
 GM_registerMenuCommand('Bookmark to Cosense', bookmarkToCosense);
 GM_registerMenuCommand('Make Cosense data', popupCosenseData);