const API_KEY = 'c48c6177536ebef4a0274b8b1bc842e249c25c51f428d1b6451923b20f69';
// const API_KEY = 'bcb577935ed755d699871072ebef6096d8ca495eb17528888027290bbda4';
const API_V0 = 'https://api.cryptorank.io/v0/';
const API_V1 = 'https://api.cryptorank.io/v1/';
const container = document.querySelector('#fetchedItems'); // items container
let activeFilter; // market | ath | gainers
let theme; // dark | light
let athSort = 'rank'

function onFilter(filter) {
    if(filter === activeFilter) return;
    activeFilter = filter;
    theme = (filter === 'gainers') ? 'light' : 'dark';

    const FMC = document.querySelector('#filterMarketCap');
    const FATH = document.querySelector('#filterATH');
    const ATHSort = document.querySelector('#ATHSort');
    const FTG = document.querySelector('#filterGainers');
    const TGSorting = document.querySelector('#topGainers');

    // Remove active class from all filter buttons
    const filters = [FMC, FATH, FTG];
    filters.forEach(i => {
        if(i.classList.contains('active')) i.classList.remove('active');
    })

    // Fetch coins by selected filter
    if(filter === 'market') {
        FMC.classList.add('active'); // Select active filter btn
        TGSorting.classList.add('hidden')
        ATHSort.classList.add('hidden')
        getMarketCap();
        theme = 'dark';
    }
    if(filter === 'ath') {
        FATH.classList.add('active'); // Select active filter btn
        ATHSort.classList.remove('hidden')
        TGSorting.classList.add('hidden')
        getATH();
        theme = 'dark';
    }
    if(filter === 'gainers') {
        FTG.classList.add('active'); // Select active filter btn
        TGSorting.classList.remove('hidden')
        ATHSort.classList.add('hidden')
        getTopGainers();
    }
}

function getMarketCap() {
    onShowPreloader();
    getCurrencies(null, 10)
        .then(async resp => {
                return [
                    resp,
                    await getCoins(resp.map(item => item.name)),
                    await getExchanges(resp.map(item => item['slug'])),
                ]
            })
        .then(([currencies, coins, exchanges]) => {
            onPrepareData(currencies, coins, exchanges)
        })
}

function getATH(sortBy, minValue) {
    onShowPreloader();
    if(minValue) { minValue = Number(minValue) }



    function sortByPrice(a, b) {
        return (a['athPrice']['USD'] === null) - (b['athPrice']['USD'] === null) || + (a['athPrice']['USD'] > b['athPrice']['USD']) || - (a['athPrice']['USD'] < b['athPrice']['USD'])
    }

    function sortByRank(a, b) {
        return (a['rank'] === null) - (b['rank'] === null) || + (a['rank'] > b['rank']) || - (a['rank'] < b['rank'])
    }

    getCoins()
        .then(resp => {
            return resp
                .filter(i => (!sortBy || sortBy === 'rank') && minValue ? i.athPrice && i.athPrice['marketCap'] : i.athPrice)
                .filter(i => minValue ? (((!sortBy || sortBy === 'rank') ? i['athPrice']['marketCap'] > minValue : i['athPrice']['USD']) > minValue) : i.athPrice)
                .sort((a,b) => new Date(a.athPrice['date']).getTime() - new Date(b.athPrice['date']).getTime())
                .reverse()
                .filter(i => i.athPrice['date'] === getFormattedTodayDate())
                .sort((a, b) => (!sortBy || sortBy === 'rank') ? sortByRank(a, b) : sortByPrice(a, b))
                .slice(0, 10);
        })
        .then(async resp => {
            return [
                resp,
                await getCurrencies(resp.map(item => item.name)),
                await getExchanges(resp.map(item => item['key'])),
            ]
        })
        .then(([coins, currencies, exchanges]) => {
            const data = coins.map(item => {
                const percentage = currencies.find(c => c.name === item.name) ? currencies.find(c => c.name === item.name).values['USD']['percentChange24h'] : null;
                const direction = currencies.find(c => c.name === item.name) ? Math.sign(currencies.find(c => c.name === item.name).values['USD']['percentChange24h']) : null;

                return {
                    coinLogo: item['image'] ? item['image'] : '',
                    ticker: item['symbol'] ? item['symbol'] : '',
                    coinName: item.name ? item.name : 'N/A',
                    marketCap: item.marketCap > 0 ? '$' + convertToAbbreviate(item.marketCap) : 'N/A',
                    percentage: percentage ? percentage.toFixed(2) : 'N/A',
                    direction: (direction && direction.toFixed(2)) === -1 ? 'down' : 'up',
                    athPrice: item.athPrice['USD'] ? convertToCurrency(item.athPrice['USD']) : 'N/A',
                    exchangeLogo: item['key'] ? exchanges.find(e => e.coin === item['key']).logo : '',
                    exchangeName: item['key'] ? exchanges.find(e => e.coin === item['key']).name : '',
                }
            })
            showData((!sortBy || sortBy === 'rank') ? data : data.reverse())
        })
}

function getTopGainers(sort) {
    const sortBy = sort ? sort : 'percentChange24h';
    onShowPreloader();

    getCurrencies()
        .then(resp => {
            return resp.filter(i => i['values']['USD'][sortBy])
                .sort((a,b) => a['values']['USD'][sortBy] - b['values']['USD'][sortBy])
                .reverse()
                .slice(0,10)
        })
        .then(async resp => {
            return [
                resp,
                await getCoins(resp.map(item => item.name)),
                // await getExchanges(resp.map(item => item['slug'])),
            ]
        })
        .then(([currencies, coins, exchanges]) => {
            onPrepareData(currencies, coins, exchanges)
        })
}

function onSortATH() {
    athSort = document.querySelector('#ATHSort').value;
    getATH(athSort);
}

function onFilterATHMin() {
    getATH(athSort, document.querySelector('#ATHMin').value)
}

function onSortGainers() {
    getTopGainers(document.querySelector('#topGainers').value);
}

function onPrepareData(currencies, coins, exchanges) {
    const data = currencies.map(item => {
        const percentage = item.values['USD']['percentChange24h'];
        const direction = Math.sign(item.values['USD']['percentChange24h']);
        const athPrice = coins.find(c => c.name === item.name).athPrice
        return {
            coinLogo: item.images ? item.images['200x200'] : '',
            ticker: item['symbol'] ? item['symbol'] : 'N/A',
            coinName: item.name ? item.name : 'N/A',
            marketCap: item.values['USD'].marketCap === 0 ? '$' + 0 : (item.values['USD'].marketCap > 0 ? '$' + convertToAbbreviate(item.values['USD'].marketCap) : 'N/A'),
            percentage: percentage ? percentage.toFixed(2) : 'N/A',
            direction: (direction && direction.toFixed(2)) === -1 ? 'down' : 'up',
            athPrice: athPrice ? convertToCurrency(coins.find(c => c.name === item.name).athPrice['USD']) : 'N/A',
            exchangeLogo: exchanges ? exchanges.find(e => e.coin === item['slug']).logo : '',
            exchangeName: exchanges ? exchanges.find(e => e.coin === item['slug']).name : 'N/A',
            volume: item.values['USD']['volume24h'] && item.values['USD']['volume24h'] > 0 ? '$' + convertToAbbreviate(item.values['USD']['volume24h']) : 'N/A'
        }
    })
    showData(data)
}

function showData(items) {
    container.innerHTML = items.map((item, index) => {
        return `
        <a href="javascript:void(0)">
            <div class="sc-card ${theme === 'dark' ? 'ath-card' : 'tg-card'}">
                <div class="sc-card-serial">
                    <span class="sc-card-serial-span ${theme === 'dark' ? 'ath' : 'tg'}-card-serial-span">${index +1}</span>
                </div>
                <div class="sc-card-icon">
                    <img src="${item['coinLogo']}" alt="" class="should-be-updated">
                </div>
                <div class="sc-card-body">
                    <div class="sc-card-body-top">
                        <div class="sc-card-heading">
                            <span class="coin-shortname">${item['ticker']}</span>
                            <span class="coin-fullname opacity-${theme === 'dark' ? '6' : '8'}">${item['coinName']}</span>
                        </div>
                        <div class="sc-card-graph">
                            <img src="./images/graph-img.svg" alt="">
                        </div>
                    </div>
                    <div class="sc-card-body-bottom">
                        <div class="sc-card-info-col">
                            <div class="sc-info-heading opacity-${theme === 'dark' ? '6' : '8'}">Market Cap</div>
                            <div class="sc-info-data">${item['marketCap']}</div>
                        </div>
                        <div class="sc-card-info-col">
                            <div class="sc-info-heading opacity-${theme === 'dark' ? '6' : '8'}">
                                ${theme === 'dark' ? 'ATH Price' : 'Price'}
                            </div>
                            <div class="sc-info-data">${item['athPrice']}</div>
                        </div>
                        <div class="sc-card-info-col">
                            <div class="sc-info-heading opacity-${theme === 'dark' ? '6' : '8'}">&percnt;24H</div>
                            <div class="sc-info-data ${theme === 'dark' ? 'ath' : 'tg'}-info-data--24h_${item['direction']}">
                                ${item['percentage']}
                                <img src="./images/${item['direction']}-icon.svg" alt="">
                            </div>
                        </div>
                        <div class="sc-card-info-col">
                            <div class="sc-info-heading opacity-${theme === 'dark' ? '6' : '8'}">
                                ${theme === 'dark' ? 'Top Exchange' : 'Volume'}
                            </div>
                            <div class="sc-info-data sc-info-data--topexchange">
                                ${theme === 'dark' ? 
                                    `
                                        <div class="topexchange-logo">
                                            <img src="${item['exchangeLogo']}" alt="" class="should-be-updated">
                                        </div>
                                        <div class="topexchange-name">${item['exchangeName']}</div>
                                    ` : `
                                        ${item.volume}
                                    `}
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </a>
    `
    }).join("");

    updateImages();
}

function onShowPreloader() {
    document.querySelector('#screenshot').classList.add('hidden');
    container.innerHTML = `<div class="preloader"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>`
}

// Helpers
async function getCoins(currencies) {
    return await fetch(API_V0 + 'coins?locale=en', {method: 'GET'})
        .then(resp => resp.json())
        .then(resp => {
            return currencies ? resp.data.filter(item => !!(currencies.find(c => c === item.name))) : resp.data;
        })
        .catch((error) => {
            console.log(error)
        })
}

async function getCurrencies(currencies, limit, sort) {
    const PARAMS = { api_key: API_KEY, limit: limit ? limit : '0', sort: sort ? sort : 'rank', optionalFields: 'images'}
    return await fetch(API_V1 + 'currencies?' + new URLSearchParams(PARAMS), {method: 'GET'})
        .then(resp => resp.json())
        .then(resp => {
            return currencies ? resp.data.filter(item => !!(currencies.find(c => c === item['name']))) : resp.data;
        })
        .catch((error) => {
            console.log(error)
        })
}

async function getExchanges(coins) {
    let promiseArray = [];
    for (let i = 0; i < coins.length; i++) {
        promiseArray.push(
            fetch(API_V0 + `coins/${coins[i]}/tickers`, {method: 'GET'})
                .then(resp => resp.json())
                .then(resp => {
                    const exchange = resp.data
                        .sort((a, b) => ((a && a['usdVolume']) > (b && b['usdVolume'])) ? 1 : -1)
                        .reverse()[0];
                    return {
                        coin: coins[i],
                        name: exchange['exchangeName'] ? exchange['exchangeName'] : 'N/A',
                        logo: exchange['exchangeIcon'] ? exchange['exchangeIcon'] : '',
                        percent: exchange['changePercent'] ? exchange['changePercent'] : ''
                    }
                })
                .catch((error) => {
                    console.log(error)
                })
        );
    }
    return Promise.all(promiseArray);
}

function convertToCurrency(str) {
    return new Intl.NumberFormat( 'en-US', {style: 'currency', currency: 'USD', maximumFractionDigits: 5}).format(str)
}

function convertToAbbreviate(num) {
    return new Intl.NumberFormat( 'en-US', { maximumFractionDigits: 2,notation: "compact" , compactDisplay: "short" }).format(num)
}

function getFormattedTodayDate(layout) {
    let monthArray = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];
    let d = new Date().toISOString();
    let month = '' + (layout ? monthArray[d.slice(5, 7) - 1] : d.slice(5, 7));
    let day = '' + d.slice(8, 10);
    let year = d.slice(0, 4);
    if (month.length < 2) { month = '0' + month }
    if (day.length < 2) { day = '0' + day }
    return layout ? [day, month, year].join(' ') : [year, month, day].join('-');
}

function takePageScreenshot() {
    const page = document.querySelector('#screen');
    const sizes = ['600', '1200', '1800'];
    sizes.forEach((size, index) => {
        page.classList.add('taking-screenshot')
        const options = {
            windowWidth: size,
            allowTaint: true,
            scale: 2,
            imageTimeout: 0
        };
        html2canvas(page, options)
            .then(canvas => {
                page.classList.remove('taking-screenshot');
                const imgName = `Satoshi Club ${getFormattedTodayDate()} x${index+1}.png`
                const downloadLink = document.createElement('a');
                downloadLink.setAttribute('download', imgName);
                canvas.toBlob(function(blob) {
                    const url = URL.createObjectURL(blob);
                    downloadLink.setAttribute('href', url);
                    downloadLink.click();
                    downloadLink.remove();
                });
            });
    })
}

function toDataURL(url, callback) {
    let canvas = document.createElement('CANVAS');
    let img = document.createElement('img');
    img.setAttribute('crossorigin', 'anonymous');
    // img.src = 'https://cors-anywhere.herokuapp.com/' + url;
    img.src = 'https://satoshi-cors.herokuapp.com/' + url;

    img.onload = () => {
        canvas.height = img.height;
        canvas.width = img.width;
        let context = canvas.getContext('2d');
        context.drawImage(img, 0, 0);
        let dataURL = canvas.toDataURL('image/png');
        canvas = null;
        callback(dataURL);
    };
}

function updateImages() {
    const images = document.getElementsByClassName("should-be-updated");
    for (let i = 0; i < images.length; i++) {
        toDataURL(images[i].src, dataUrl => {
            return images[i].src = dataUrl
        })
    }
    document.querySelector('#screenshot').classList.remove('hidden');
}


document.querySelector('#date').textContent = getFormattedTodayDate(true); // Display today date
