var fnp = {
    defaultCoverFnp: '/resources/no-cover.png',
    defaultCoverLfm: 'https://lastfm.freetls.fastly.net/i/u/300x300/2a96cbd8b46e442fc41c2b86b821562f.png',
    watch: {
        interval: 15 * 1000,
        userName: '',
        timeOut: 0,
        stopping: false,
    },
    ui: {
        mode: '',
        bgSwitch: false,
        currBg: '',
        coverSwitch: false,
        currCover: '',
    },
};

fnp.goIndex = function() {
    location.hash = '';
};
fnp.switchUser = function(userName) {
    location.hash = '#/' + encodeURIComponent((userName ?? '').toString());
};

fnp.updateHash = function() {
    var userName = decodeURIComponent(location.hash.substring(2));

    this.ui.setBackgroundFade();
    this.ui.goLoading();

    if(userName.length > 0) {
        this.watch.start(userName, function(response) {
            if(response.error) {
                this.goIndex();
                alert(response.error);
                return;
            }

            var coverUrl = response[0].images.extralarge;
            if(coverUrl.length < 1 || coverUrl === this.defaultCoverLfm)
                coverUrl = this.defaultCoverFnp;

            this.ui.setBackground(coverUrl);
            this.ui.setCover(coverUrl);
            this.ui.setTitle(response[0].name, response[0].url);
            this.ui.setArtist(response[0].artist.name, response[0].artist.url);
            this.ui.setCurrentUser(userName, 'https://www.last.fm/user/' + encodeURIComponent(userName));
            this.ui.setNowListening(response[0].nowplaying || false);
            this.ui.goUser();
        }.bind(this));
    } else {
        this.watch.stop(function() {
            this.ui.goIndex();
        }.bind(this));
    }
};

fnp.watch.start = function(userName, callback) {
    this.stop();
    this.userName = userName = (userName || '').toString();

    this.callback = function(response) {
        if(this.stopping)
            return;

        if(response.error)
            this.stop();
        else
            this.timeOut = setTimeout(this.fetch.bind(this), this.interval);

        callback(response);
    };
    this.callback.bind(this);

    this.fetch();
};
fnp.watch.stop = function(callback) {
    if(this.stopping)
        return;
    this.stopping = true;

    if(this.timeOut !== 0) {
        clearTimeout(this.timeOut);
        this.timeOut = 0;
    }

    this.userName = '';

    if(callback)
        callback();
    this.stopping = false;
};
fnp.watch.fetch = function() {
    if(typeof this.callback !== 'function')
        return;
    var xhr = new XMLHttpRequest;
    xhr.onreadystatechange = function() {
        if(xhr.readyState !== 4)
            return;
        this.callback(JSON.parse(xhr.responseText));
    }.bind(this);
    xhr.open('GET', '/get.php?u=' + encodeURIComponent(this.userName));
    xhr.send();
};

fnp.ui.setMode = function(modeName) {
    modeName = (modeName || '').toString();
    if(this.mode === modeName)
        return;
    this.mode = modeName;

    for(var i = 0; i < this.modes.length; ++i) {
        var mode = this.modes[i];
        mode.elem.classList[mode.name === modeName ? 'remove' : 'add']('hidden');
    }
};
fnp.ui.goIndex = function() {
    this.setMode('index');
};
fnp.ui.goUser = function() {
    this.setMode('user');
};
fnp.ui.goLoading = function() {
    this.setMode('loading');
};

fnp.ui.setBackground = function(bgPath) {
    if(bgPath === '::fade') {
        this.setBackgroundFade();
        return;
    }

    if(this.iColourFade !== 0) {
        clearInterval(this.iColourFade);
        this.iColourFade = 0;
    }

    this.eBg.style.backgroundColor = null;
    this.switchBackground(bgPath);
};
fnp.ui.switchBackground = function(bgPath) {
    if(bgPath === this.currBg)
        return;

    if(this.bgSwitch) {
        setTimeout(this.switchBackground.bind(this, bgPath), 1000);
        return;
    }

    this.bgSwitch = true;
    this.currBg = bgPath;

    while(this.eBg.children.length > 2)
        this.eBg.removeChild(this.eBg.firstChild);

    var newBg = null,
        hasNewBg = !!bgPath,
        oldBg = this.eBg.firstChild,
        hasOldBg = !!oldBg;

    if(hasOldBg)
        oldBg.style.zIndex = '-1';

    if(hasNewBg) {
        newBg = document.createElement('img');
        newBg.alt = newBg.src = bgPath;
        newBg.style.opacity = '0';
        newBg.style.zIndex = '1';
        newBg.onload = function() {
            setTimeout(function() {
                newBg.style.opacity = null;
                setTimeout(function() {
                    newBg.style.zIndex = null;
                    if(hasOldBg)
                        this.eBg.removeChild(oldBg);
                    this.bgSwitch = false;
                }.bind(this), 500);
            }.bind(this), 50);
        }.bind(this);
        newBg.onerror = function() {
            this.eBg.removeChild(newBg);
            newBg = null;
            hasNewBg = false;
            this.bgSwitch = false;
        }.bind(this);
        this.eBg.appendChild(newBg);
    } else if(hasOldBg) {
        oldBg.style.opacity = '0';
        setTimeout(function() {
            this.eBg.removeChild(oldBg);
            this.bgSwitch = false;
        }.bind(this), 500);
    } else {
        this.bgSwitch = false;
    }
};
fnp.ui.removeBackground = function() {
    this.switchBackground('');
};
fnp.ui.setBackgroundFade = function() {
    if(this.iColourFade !== 0)
        return;

    this.removeBackground();

    var fader = function() {
        var colour = Math.floor(Math.random() * 0xFFFFFF).toString(16);

        if(colour.length !== 6 && colour.length !== 3)
            colour = '000000'.substring(colour.length) + colour;

        this.eBg.style.backgroundColor = '#' + colour;
    }.bind(this);

    this.iColourFade = setInterval(fader, 2000);
    fader();
};

fnp.ui.setCover = function(coverUrl) {
    this.switchCover(coverUrl);
};
fnp.ui.switchCover = function(coverUrl) {
    if(coverUrl === this.currCover)
        return;

    if(this.coverSwitch) {
        setTimeout(this.switchCover.bind(this, coverUrl), 1000);
        return;
    }

    this.coverSwitch = true;
    this.currCover = coverUrl;

    while(this.eInfoCover.children.length > 2)
        this.eInfoCover.removeChild(this.eInfoCover.firstChild);

    var newCover = null,
        hasNewCover = !!coverUrl,
        oldCover = this.eInfoCover.firstChild,
        hasOldCover = !!oldCover;

    if(hasOldCover)
        oldCover.style.zIndex = '-1';

    if(hasNewCover) {
        newCover = document.createElement('img');
        newCover.alt = newCover.src = coverUrl;
        newCover.style.opacity = '0';
        newCover.style.zIndex = '1';
        newCover.onload = function() {
            setTimeout(function() {
                newCover.style.opacity = null;
                setTimeout(function() {
                    newCover.style.zIndex = null;
                    if(hasOldCover)
                        this.eInfoCover.removeChild(oldCover);
                    this.coverSwitch = false;
                }.bind(this), 500);
            }.bind(this), 50);
        }.bind(this);
        newCover.onerror = function() {
            this.eInfoCover.removeChild(newCover);
            newCover = null;
            hasNewBg = false;
            this.coverSwitch = false;
        }.bind(this);
        this.eInfoCover.appendChild(newCover);
    } else if(hasOldCover) {
        oldCover.style.opacity = '0';
        setTimeout(function() {
            this.eInfoCover.removeChild(oldCover);
            this.coverSwitch = false;
        }.bind(this), 500);
    } else {
        this.coverSwitch = false;
    }
};
fnp.ui.removeCover = function() {
    this.switchCover('');
};
fnp.ui.setTitle = function(title, url) {
    this.eInfoTitle.textContent = (title || '').toString();
    if(url) this.eInfoTitle.href = url.toString();
};
fnp.ui.setArtist = function(title, url) {
    this.eInfoArtist.textContent = (title || '').toString();
    if(url) this.eInfoArtist.href = url.toString();
};
fnp.ui.setCurrentUser = function(title, url) {
    this.eInfoUser.textContent = (title || '').toString();
    if(url) this.eInfoUser.href = url.toString();
};
fnp.ui.setNowListening = function(state) {
    this.eInfoFlags.innerHTML = '';

    if(state) {
        var nowIcon = document.createElement('span');
        nowIcon.className = 'fa fa-music';
        nowIcon.title = 'Now playing';
        this.eInfoFlags.appendChild(nowIcon);
    }
};

window.onload = function() {
    fnp.ui.eIndex = document.getElementById('index');
    fnp.ui.eUser = document.getElementById('user');
    fnp.ui.eLoading = document.getElementById('loading');
    fnp.ui.eBg = document.getElementById('background');
    fnp.ui.eFormUser = document.getElementById('username');
    fnp.ui.eFormSend = document.getElementById('submit');
    fnp.ui.eInfoCover = document.getElementById('np_cover');
    fnp.ui.eInfoTitle = document.getElementById('np_title');
    fnp.ui.eInfoArtist = document.getElementById('np_artist');
    fnp.ui.eInfoUser = document.getElementById('np_user');
    fnp.ui.eInfoBack = document.getElementById('np_back');
    fnp.ui.eInfoFlags = document.getElementById('np_flags');
    fnp.ui.iColourFade = 0;
    fnp.ui.modes = [
        { name: 'index', elem: fnp.ui.eIndex },
        { name: 'user',  elem: fnp.ui.eUser },
        { name: 'loading',  elem: fnp.ui.eLoading },
    ];

    fnp.ui.eInfoBack.onclick = function() {
        fnp.goIndex();
    };

    window.onhashchange = function() {
        fnp.updateHash();
    };

    fnp.ui.eFormSend.onclick = function() {
        fnp.switchUser(fnp.ui.eFormUser.value);
    };

    fnp.ui.eFormUser.onkeydown = function(ev) {
        if(typeof ev.key === 'undefined')
            ev.key = ev.keyCode === 13 ? 'Enter' : '?';

        if(ev.key === 'Enter' || ev.key === 'NumpadEnter')
            fnp.switchUser(fnp.ui.eFormUser.value);
    };

    fnp.updateHash();
};