/*
extension background script listening for events
*/

'use strict';

console.log('running background.js');

let browserType = getBrowser();

// boilerplate to dedect browser type api
function getBrowser() {
  if (typeof chrome !== 'undefined') {
    if (typeof browser !== 'undefined') {
      return browser;
    } else {
      return chrome;
    }
  } else {
    console.log('failed to detect browser');
    throw 'browser detection error';
  }
}

// send get request to API backend
async function sendGet(path) {
  let access = await getAccess();
  const url = `${access.url}:${access.port}/${path}`;
  console.log('GET: ' + url);

  const rawResponse = await fetch(url, {
    method: 'GET',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      Authorization: 'Token ' + access.apiKey,
      mode: 'no-cors',
    },
  });

  const content = await rawResponse.json();
  return content;
}

// send post/put request to API backend
async function sendData(path, payload, method) {
  let access = await getAccess();
  const url = `${access.url}:${access.port}/${path}`;
  console.log(`${method}: ${url}`);
  console.log(`${method}: ${JSON.stringify(payload)}`);

  try {
    const rawResponse = await fetch(url, {
      method: method,
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        Authorization: 'Token ' + access.apiKey,
        mode: 'no-cors',
      },
      body: JSON.stringify(payload),
    });
    const content = await rawResponse.json();
    return content;
  } catch (e) {
    console.error(e);
    return null;
  }
}

// read access details from storage.local
async function getAccess() {
  let storage = await browserType.storage.local.get('access');

  return storage.access;
}

// check if cookie is valid
async function getCookieState() {
  const path = 'api/cookie/';
  let response = await sendGet(path);
  console.log('cookie state: ' + JSON.stringify(response));

  return response;
}

// send ping to server, return response
async function verifyConnection() {
  const path = 'api/ping/';
  let response = await sendGet(path);
  console.log('verify connection: ' + JSON.stringify(response));

  return response;
}

// send youtube link from injected buttons
async function youtubeLink(youtubeMessage) {
  let path;
  let payload;

  if (youtubeMessage.action === 'download') {
    path = 'api/download/';
    payload = {
      data: [
        {
          youtube_id: youtubeMessage.url,
          status: 'pending',
        },
      ],
    };
  } else if (youtubeMessage.action === 'subscribe') {
    path = 'api/channel/';
    payload = {
      data: [
        {
          channel_id: youtubeMessage.url,
          channel_subscribed: true,
        },
      ],
    };
  }

  let response = await sendData(path, payload, 'POST');
  return response;
}

async function cookieStr(cookieLines) {
  const path = 'api/cookie/';
  let payload = {
    cookie: cookieLines.join('\n'),
  };
  let response = await sendData(path, payload, 'PUT');

  return response;
}

function buildCookieLine(cookie) {
  return [
    cookie.domain,
    'TRUE',
    cookie.path,
    cookie.httpOnly.toString().toUpperCase(),
    Math.trunc(cookie.expirationDate) || 0,
    cookie.name,
    cookie.value,
  ].join('\t');
}

async function sendCookies() {
  console.log('function sendCookies');

  let cookieStores = await browserType.cookies.getAllCookieStores();
  let cookieLines = [
    '# Netscape HTTP Cookie File',
    '# https://curl.haxx.se/rfc/cookie_spec.html',
    '# This is a generated file! Do not edit.\n',
  ];
  for (let i = 0; i < cookieStores.length; i++) {
    const cookieStore = cookieStores[i];
    let allCookiesStore = await browserType.cookies.getAll({
      domain: '.youtube.com',
      storeId: cookieStore['id'],
    });
    for (let j = 0; j < allCookiesStore.length; j++) {
      const cookie = allCookiesStore[j];
      cookieLines.push(buildCookieLine(cookie));
    }
  }

  let response = cookieStr(cookieLines);

  return response;
}

// process and return message if needed
function handleMessage(request, sender, sendResponse) {
  console.log('message background.js listener: ' + JSON.stringify(request));

  if (request.verify === true) {
    let response = verifyConnection();
    response.then(message => {
      sendResponse(message);
    });
  } else if (request.youtube) {
    let response = youtubeLink(request.youtube);
    response.then(message => {
      sendResponse(message);
    });
  } else if (request.cookieState) {
    let response = getCookieState();
    response.then(message => {
      sendResponse(message);
    });
  } else if (request.sendCookie) {
    console.log('backgound: ' + JSON.stringify(request));
    let response = sendCookies();
    response.then(message => {
      sendResponse(message);
    });
  }

  return true;
}

browserType.runtime.onMessage.addListener(handleMessage);
