<!DOCTYPE html>
<html lang="en">
<head>
    <title>Tabs</title>

    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css"
          integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay" crossorigin="anonymous">

    <link rel="stylesheet" href="layout.css">

    <style>
        body {
            display: flex;
            flex-direction: row;
        }

        #service-selector {
            flex-grow: 1;
            display: block;
            margin: 0;
            padding: 0;
        }

        *:focus {
            outline-color: rgb(118, 93, 176);
        }

        #navigation button {
            display: block;
            width: 100%;
            padding: 16px;
            margin: 0;
            height: 72px;

            color: #fff;
            border: 0;
            background: transparent;

            cursor: pointer;
        }

        #navigation button img {
            width: 32px;
        }

        #navigation button i {
            font-size: 32px;
        }

        #service-selector li.active button {
            position: relative;
            background-color: #fff2;
        }

        #service-selector li.active button::before {
            content: "";
            display: block;
            position: absolute;
            left: 0;
            top: 0;
            height: 100%;
            border-left: 4px solid #ffffff2e;
        }

        #navigation button:hover {
            background-color: #fff3;
        }

        #history {
            padding: 8px;
        }

        #history button {
            display: inline;
            width: 24px;
            height: 24px;
            padding: initial;
            font-size: 12px;

            background: #fff1;
            border: 1px solid #fff4;
            border-radius: 72px;

            color: #fff;
            cursor: pointer;
        }

        #history button i {
            font-size: inherit;
        }

        #history button.disabled {
            color: #888;
            border: transparent;
            background: transparent;
            cursor: initial;
        }

        #history button:focus,
        #history button:hover {
            outline: none;
            border-color: #fff9;
        }

        #history button:hover:not(.disabled) {
            outline: none;
            background-color: #fff2;
        }

        #history button:active:not(.disabled) {
            background-color: #fff4;
        }

        #navigation #add-button:not(:hover) {
            opacity: 0.75;
        }

        #services {
            position: relative;
            flex-grow: 1;
        }

        #services > *:not(.loader) {
            height: 100%;
        }

        #services > :not(.active):not(.loader) {
            display: none;
        }

        #services > .loader {
            width: 64px;
            height: 64px;

            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            z-index: -1;
        }
    </style>
</head>

<body>
<div id="navigation">
    <div id="history">
        <button id="back"><i class="fas fa-arrow-left"></i></button>
        <button id="forward" class="disabled"><i class="fas fa-arrow-right"></i></button>
    </div>

    <ul id="service-selector"></ul>

    <button id="add-button"><i class="fa fa-plus"></i></button>

    <button id="settings-button"><i class="fa fa-cog"></i></button>
</div>

<div id="services">
    <div class="loader"></div>
</div>

<script>
    const {
        remote,
        ipcRenderer,
    } = require('electron');
    const {
        Menu,
        MenuItem,
    } = remote;

    const icons = [];

    let services = [];
    let selectedService = 0;
    let forwardButton;
    let backButton;
    let addButton;


    // Service context menu
    const serviceContextMenu = new Menu();
    const settingsItem = new MenuItem({
        label: 'Edit', click: () => {
            ipcRenderer.send('openServiceSettings', serviceContextMenu.serviceId);
        }
    });
    serviceContextMenu.append(settingsItem);

    function openServiceContextMenu(event, index) {
        event.preventDefault();
        serviceContextMenu.serviceId = index;
        serviceContextMenu.popup({window: remote.getCurrentWindow()});
    }


    ipcRenderer.on('data', (event, brandIcons, solidIcons, actualServices, actualSelectedService) => {
        for (const icon of brandIcons) {
            icons.push(icon);
        }
        for (const icon of solidIcons) {
            icons.push(icon);
        }

        console.log('Updating services ...');
        services = actualServices;

        const nav = document.querySelector('#service-selector');
        while (nav.children.length > 0) {
            nav.removeChild(nav.children[0]);
        }

        const serviceContainer = document.querySelector('#services');
        serviceContainer.querySelectorAll(":scope > webview").forEach(w => serviceContainer.removeChild(w));

        for (let i = 0; i < services.length; i++) {
            createService(i);
        }
        setActiveService(actualSelectedService);
    });

    ipcRenderer.on('updateService', (e, id, data) => {
        if (id === null) {
            services.push(data);
            createService(services.length - 1);
        } else {
            let nav = document.querySelector('#service-selector');

            // Remove nav
            const oldNavButton = nav.querySelector('li:nth-of-type(' + (id + 1) + ')');
            const nextNavButton = oldNavButton.nextSibling;
            nav.removeChild(oldNavButton);

            // Remove webview
            if (services[id].view) {
                const serviceContainer = document.querySelector('#services');
                serviceContainer.removeChild(services[id].view);
            }

            // Create new service
            services[id] = data;
            createService(id, nextNavButton);
            if (parseInt(selectedService) === id) {
                setActiveService(id);
            }
        }
    });

    function createService(index, nextNavButton) {
        let service = services[index];
        let li = document.createElement('li');
        service.li = li;

        let button = document.createElement('button');
        button.dataset.serviceId = '' + index;
        button.dataset.tooltip = service.name;
        button.addEventListener('click', () => {
            setActiveService(button.dataset.serviceId);
            ipcRenderer.send('setActiveService', button.dataset.serviceId);
        });
        button.addEventListener('contextmenu', e => openServiceContextMenu(e, index));

        let icon;
        if (service.useFavicon && service.favicon != null) {
            icon = document.createElement('img');
            icon.src = service.favicon;
            icon.alt = service.name;
        } else if (service.isImage) {
            icon = document.createElement('img');
            icon.src = service.icon;
            icon.alt = service.name;
        } else {
            icon = document.createElement('i');
            const iconProperties = icons.find(i => i.name === service.icon);
            if (iconProperties) {
                iconProperties.faIcon.split(' ').forEach(cl => {
                    icon.classList.add(cl);
                });
            }
        }

        button.appendChild(icon);
        li.appendChild(button);
        li.button = button;

        const nav = document.querySelector('#service-selector');
        if (nextNavButton === nav || nextNavButton === undefined) {
            nav.appendChild(li);
        } else {
            nav.insertBefore(li, nextNavButton);
        }
    }

    document.addEventListener('DOMContentLoaded', () => {
        forwardButton = document.querySelector('#forward');
        forwardButton.addEventListener('click', () => goForward());

        backButton = document.querySelector('#back');
        backButton.addEventListener('click', () => goBack());

        addButton = document.querySelector('#add-button');
        addButton.addEventListener('click', () => ipcRenderer.send('openServiceSettings', null));
    });

    function setActiveService(serviceId) {
        let currentService = services[serviceId];
        process.nextTick(() => {
            // Load service if not loaded yet
            if (!currentService.view) {
                currentService.view = document.createElement('webview');
                currentService.view.setAttribute('src', currentService.url);
                currentService.view.setAttribute('partition', 'persist:service_' + currentService.partition);
                currentService.view.setAttribute('autosize', "true");

                document.querySelector('#services').appendChild(currentService.view);
                currentService.view.addEventListener('dom-ready', event => {
                    currentService.viewReady = true;
                    updateNavigation();
                });
                currentService.view.addEventListener('page-favicon-updated', event => {
                    console.debug('Loaded favicons for', currentService.name, event.favicons);
                    if (event.favicons.length > 0) {
                        ipcRenderer.send('setServiceFavicon', serviceId, event.favicons[0]);
                        if (currentService.useFavicon) {
                            const img = document.createElement('img');
                            img.src = event.favicons[0];
                            img.alt = currentService.name;
                            img.onload = () => {
                                currentService.li.button.innerHTML = '';
                                currentService.li.button.appendChild(img);
                            };
                        }
                    }
                });
            }

            // Hide previous service
            if (services[selectedService].view) {
                services[selectedService].view.classList.remove('active');
            }

            // Show service
            currentService.view.classList.add('active');

            // Save active service ID
            selectedService = serviceId;

            // Refresh navigation
            updateNavigation();
        });
    }

    function updateNavigation() {
        console.debug('Updating navigation');
        // Update active list element
        for (let i = 0; i < services.length; i++) {
            let service = services[i];
            if (parseInt(selectedService) === i) {
                service.li.classList.add('active');
            } else {
                service.li.classList.remove('active');
            }
        }

        if (services[selectedService].viewReady) {
            console.debug('Updating navigation buttons because view is ready');
            // Update history navigation
            let view = services[selectedService].view;

            if (view && view.canGoForward()) forwardButton.classList.remove('disabled');
            else forwardButton.classList.add('disabled');

            if (view && view.canGoBack()) backButton.classList.remove('disabled');
            else backButton.classList.add('disabled');
        }
    }

    function goForward() {
        let view = services[selectedService].view;
        if (view) view.getWebContents().goForward();
    }

    function goBack() {
        let view = services[selectedService].view;
        if (view) view.getWebContents().goBack();
    }
</script>
</body>

</html>