'use strict';

/* eslint-disable newline-per-chained-call */
const bhttp = require('bhttp');
const { JSDOM } = require('jsdom');
const cheerio = require('cheerio');
const moment = require('moment');

const descriptionTags = {
    'anal cream pie': 'anal creampie',
    'ass to mouth': 'ass to mouth',
    'cream pie in her ass': 'anal creampie',
    'eats ass': 'ass eating',
    facial: 'facial',
    gaped: 'gaping',
    gapes: 'gaping',
    gape: 'gaping',
    'rectal cream pie': 'anal creampie',
    rimming: 'ass eating',
};

function deriveTagsFromDescription(description) {
    const matches = (description || '').toLowerCase().match(new RegExp(Object.keys(descriptionTags).join('|'), 'g'));

    return matches
        ? matches.map(match => descriptionTags[match])
        : [];
}

async function scrapeLatestA(html, site) {
    const { document } = new JSDOM(html).window;
    const sceneElements = document.querySelectorAll('.content-item-large, .content-item');

    return Promise.all(Array.from(sceneElements, async (element) => {
        const $ = cheerio.load(element.innerHTML, { normalizeWhitespace: true });

        const titleElement = element.querySelector('h3.title a');
        const title = titleElement.textContent;
        const url = titleElement.href;
        const entryId = url.split('/').slice(-2)[0];

        const descriptionElement = element.querySelector('.desc');
        const description = descriptionElement && descriptionElement.textContent.trim();
        const date = moment(element.querySelector('.date, time').textContent, 'Do MMM YYYY').toDate();

        const actors = Array.from(element.querySelectorAll('h4.models a'), actorElement => actorElement.textContent);

        const durationString = element.querySelector('.total-time').textContent.trim();
        // timestamp is sometimes 00:00, sometimes 0:00:00
        const duration = durationString.split(':').length === 3
            ? moment.duration(durationString).asSeconds()
            : moment.duration(`00:${durationString}`).asSeconds();

        const ratingElement = element.querySelector('.rating');
        const stars = ratingElement && ratingElement.dataset.rating;

        const [poster, ...primaryPhotos] = Array.from(element.querySelectorAll('img'), imageElement => imageElement.src);
        const secondaryPhotos = $('.thumb-top, .thumb-bottom')
            .map((photoIndex, photoElement) => $(photoElement).css()['background-image'])
            .toArray()
            .map(photoUrl => photoUrl.slice(photoUrl.indexOf('http'), photoUrl.indexOf('.jpg') + 4));

        const photos = [...primaryPhotos, ...secondaryPhotos];
        const tags = deriveTagsFromDescription(description);

        const scene = {
            url,
            entryId,
            title,
            description,
            actors,
            director: 'Mike Adriano',
            date,
            duration,
            tags,
            poster,
            photos,
            rating: {
                stars,
            },
            site,
        };

        return scene;
    }));
}

async function scrapeLatestB(html, site) {
    const { document } = new JSDOM(html).window;
    const sceneElements = document.querySelectorAll('.content-border');

    return Promise.all(Array.from(sceneElements, async (element) => {
        const $ = cheerio.load(element.innerHTML, { normalizeWhitespace: true });

        const titleElement = element.querySelector('.content-title-wrap a');
        const title = titleElement.title || titleElement.textContent.trim();
        const url = titleElement.href;
        const entryId = url.split('/').slice(-2)[0];

        const description = element.querySelector('.content-description').textContent.trim();
        const date = (moment(element.querySelector('.mobile-date').textContent, 'MM/DD/YYYY')
            || moment(element.querySelector('.date').textContent, 'Do MMM YYYY')).toDate();
        const actors = Array.from(element.querySelectorAll('.content-models a'), actorElement => actorElement.textContent);

        const durationString = element.querySelector('.total-time').textContent.trim();
        // timestamp is somethines 00:00, sometimes 0:00:00
        const duration = durationString.split(':').length === 3
            ? moment.duration(durationString).asSeconds()
            : moment.duration(`00:${durationString}`).asSeconds();

        const [poster, ...primaryPhotos] = Array.from(element.querySelectorAll('a img'), imageElement => imageElement.src);
        const secondaryPhotos = $('.thumb-mouseover')
            .map((photoIndex, photoElement) => $(photoElement).css()['background-image'])
            .toArray()
            .map(photoUrl => photoUrl.slice(photoUrl.indexOf('http'), photoUrl.indexOf('.jpg') + 4));

        const photos = [...primaryPhotos, ...secondaryPhotos];
        const tags = deriveTagsFromDescription(description);

        return {
            url,
            entryId,
            title,
            description,
            actors,
            director: 'Mike Adriano',
            date,
            duration,
            tags,
            poster,
            photos,
            site,
        };
    }));
}

async function scrapeSceneA(html, url, site) {
    const { document } = new JSDOM(html).window;
    const element = document.querySelector('.content-page-info');

    const entryId = url.split('/').slice(-2)[0];
    const title = element.querySelector('.title').textContent.trim();
    const description = element.querySelector('.desc').textContent.trim();
    const date = moment(element.querySelector('.post-date').textContent.trim(), 'Do MMM YYYY').toDate();

    const actors = Array.from(element.querySelectorAll('.models a'), actorElement => actorElement.textContent);

    const durationString = element.querySelector('.total-time').textContent.trim();
    // timestamp is sometimes 00:00, sometimes 0:00:00
    const duration = durationString.split(':').length === 3
        ? moment.duration(durationString).asSeconds()
        : moment.duration(`00:${durationString}`).asSeconds();

    const { poster } = document.querySelector('.content-page-header video');
    const { src, type } = document.querySelector('.content-page-header source');

    const tags = deriveTagsFromDescription(description);

    return {
        url,
        entryId,
        title,
        description,
        actors,
        director: 'Mike Adriano',
        date,
        duration,
        tags,
        poster,
        trailer: {
            src,
            type,
        },
        site,
    };
}

async function scrapeSceneB(html, url, site) {
    const { document } = new JSDOM(html).window;
    const element = document.querySelector('.content-page-info');

    const entryId = url.split('/').slice(-2)[0];
    const title = element.querySelector('.title').textContent.trim();
    const description = element.querySelector('.desc').textContent.trim();
    const date = moment(element.querySelector('.date').textContent.trim(), 'Do MMM YYYY').toDate();

    const actors = Array.from(element.querySelectorAll('.models a'), actorElement => actorElement.textContent);

    const durationString = element.querySelector('.total-time').textContent.trim();
    // timestamp is somethines 00:00, sometimes 0:00:00
    const duration = durationString.split(':').length === 3
        ? moment.duration(durationString).asSeconds()
        : moment.duration(`00:${durationString}`).asSeconds();

    const { poster } = document.querySelector('.content-page-header-inner video');
    const { src, type } = document.querySelector('.content-page-header-inner source');

    const tags = deriveTagsFromDescription(description);

    const scene = {
        url,
        entryId,
        title,
        description,
        actors,
        director: 'Mike Adriano',
        date,
        duration,
        tags,
        poster,
        trailer: {
            src,
            type,
        },
        site,
    };

    return scene;
}

async function fetchLatest(site, page = 1) {
    const { host } = new URL(site.url);

    const res = await bhttp.get(`https://tour.${host}/videos?page=${page}`);

    if (host === 'trueanal.com' || host === 'swallowed.com') {
        return scrapeLatestA(res.body.toString(), site);
    }

    return scrapeLatestB(res.body.toString(), site);
}

async function fetchScene(url, site) {
    const { host } = new URL(site.url);
    const res = await bhttp.get(url);

    if (host === 'trueanal.com' || host === 'swallowed.com') {
        return scrapeSceneA(res.body.toString(), url, site);
    }

    return scrapeSceneB(res.body.toString(), url, site);
}

module.exports = {
    fetchLatest,
    fetchScene,
};
