import store from 'store';
import S from 'string';
import {
    checkIfAuth,
    urlpath
} from './common';

window.migrateHistoryFromTempCallback = null;

migrateHistoryFromTemp();

function migrateHistoryFromTemp() {
    if (url('#tempid')) {
        $.get(`${serverurl}/temp`, {
                tempid: url('#tempid')
            })
            .done(data => {
                if (data && data.temp) {
                    getStorageHistory(olddata => {
                        if (!olddata || olddata.length == 0) {
                            saveHistoryToStorage(JSON.parse(data.temp));
                        }
                    });
                }
            })
            .always(() => {
                let hash = location.hash.split('#')[1];
                hash = hash.split('&');
                for (let i = 0; i < hash.length; i++)
                    if (hash[i].indexOf('tempid') == 0) {
                        hash.splice(i, 1);
                        i--;
                    }
                hash = hash.join('&');
                location.hash = hash;
                if (migrateHistoryFromTempCallback)
                    migrateHistoryFromTempCallback();
            });
    }
}

export function saveHistory(notehistory) {
    checkIfAuth(
        () => {
            saveHistoryToServer(notehistory);
        },
        () => {
            saveHistoryToStorage(notehistory);
        }
    );
}

function saveHistoryToStorage(notehistory) {
    if (store.enabled)
        store.set('notehistory', JSON.stringify(notehistory));
    else
        saveHistoryToCookie(notehistory);
}

function saveHistoryToCookie(notehistory) {
    Cookies.set('notehistory', notehistory, {
        expires: 365
    });
}

function saveHistoryToServer(notehistory) {
    $.post(`${serverurl}/history`, {
        history: JSON.stringify(notehistory)
    });
}

function saveCookieHistoryToStorage(callback) {
    store.set('notehistory', Cookies.get('notehistory'));
    callback();
}

export function saveStorageHistoryToServer(callback) {
    const data = store.get('notehistory');
    if (data) {
        $.post(`${serverurl}/history`, {
                history: data
            })
            .done(data => {
                callback(data);
            });
    }
}

function saveCookieHistoryToServer(callback) {
    $.post(`${serverurl}/history`, {
            history: Cookies.get('notehistory')
        })
        .done(data => {
            callback(data);
        });
}

export function clearDuplicatedHistory(notehistory) {
    const newnotehistory = [];
    for (let i = 0; i < notehistory.length; i++) {
        let found = false;
        for (let j = 0; j < newnotehistory.length; j++) {
            const id = notehistory[i].id.replace(/\=+$/, '');
            const newId = newnotehistory[j].id.replace(/\=+$/, '');
            if (id == newId || notehistory[i].id == newnotehistory[j].id || !notehistory[i].id || !newnotehistory[j].id) {
                const time = (typeof notehistory[i].time === 'number' ? moment(notehistory[i].time) : moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a'));
                const newTime = (typeof newnotehistory[i].time === 'number' ? moment(newnotehistory[i].time) : moment(newnotehistory[i].time, 'MMMM Do YYYY, h:mm:ss a'));
                if(time >= newTime) {
                    newnotehistory[j] = notehistory[i];
                }
                found = true;
                break;
            }
        }
        if (!found)
            newnotehistory.push(notehistory[i]);
    }
    return newnotehistory;
}

function addHistory(id, text, time, tags, pinned, notehistory) {
    // only add when note id exists
    if (id) {
      notehistory.push({
          id,
          text,
          time,
          tags,
          pinned
      });
    }
    return notehistory;
}

export function removeHistory(id, notehistory) {
    for (let i = 0; i < notehistory.length; i++) {
        if (notehistory[i].id == id) {
            notehistory.splice(i, 1);
            i -= 1;
        }
    }
    return notehistory;
}

//used for inner
export function writeHistory(title, tags) {
    checkIfAuth(
        () => {
            // no need to do this anymore, this will count from server-side
            // writeHistoryToServer(title, tags);
        },
        () => {
            writeHistoryToStorage(title, tags);
        }
    );
}

function writeHistoryToServer(title, tags) {
    $.get(`${serverurl}/history`)
        .done(data => {
            try {
                if (data.history) {
                    var notehistory = data.history;
                } else {
                    var notehistory = [];
                }
            } catch (err) {
                var notehistory = [];
            }
            if (!notehistory)
                notehistory = [];

            const newnotehistory = generateHistory(title, tags, notehistory);
            saveHistoryToServer(newnotehistory);
        })
        .fail((xhr, status, error) => {
            console.error(xhr.responseText);
        });
}

function writeHistoryToCookie(title, tags) {
    try {
        var notehistory = Cookies.getJSON('notehistory');
    } catch (err) {
        var notehistory = [];
    }
    if (!notehistory)
        notehistory = [];

    const newnotehistory = generateHistory(title, tags, notehistory);
    saveHistoryToCookie(newnotehistory);
}

function writeHistoryToStorage(title, tags) {
    if (store.enabled) {
        let data = store.get('notehistory');
        if (data) {
            if (typeof data == "string")
                data = JSON.parse(data);
            var notehistory = data;
        } else
            var notehistory = [];
        if (!notehistory)
            notehistory = [];

        const newnotehistory = generateHistory(title, tags, notehistory);
        saveHistoryToStorage(newnotehistory);
    } else {
        writeHistoryToCookie(title, tags);
    }
}

if (!Array.isArray) {
    Array.isArray = arg => Object.prototype.toString.call(arg) === '[object Array]';
}

function renderHistory(title, tags) {
    //console.debug(tags);
    const id = urlpath ? location.pathname.slice(urlpath.length + 1, location.pathname.length).split('/')[1] : location.pathname.split('/')[1];
    return {
        id,
        text: title,
        time: moment().valueOf(),
        tags
    };
}

function generateHistory(title, tags, notehistory) {
    const info = renderHistory(title, tags);
    //keep any pinned data
    let pinned = false;
    for (let i = 0; i < notehistory.length; i++) {
        if (notehistory[i].id == info.id && notehistory[i].pinned) {
            pinned = true;
            break;
        }
    }
    notehistory = removeHistory(info.id, notehistory);
    notehistory = addHistory(info.id, info.text, info.time, info.tags, pinned, notehistory);
    notehistory = clearDuplicatedHistory(notehistory);
    return notehistory;
}

//used for outer
export function getHistory(callback) {
    checkIfAuth(
        () => {
            getServerHistory(callback);
        },
        () => {
            getStorageHistory(callback);
        }
    );
}

function getServerHistory(callback) {
    $.get(`${serverurl}/history`)
        .done(data => {
            if (data.history) {
                callback(data.history);
            }
        })
        .fail((xhr, status, error) => {
            console.error(xhr.responseText);
        });
}

function getCookieHistory(callback) {
    callback(Cookies.getJSON('notehistory'));
}

export function getStorageHistory(callback) {
    if (store.enabled) {
        let data = store.get('notehistory');
        if (data) {
            if (typeof data == "string")
                data = JSON.parse(data);
            callback(data);
        } else
            getCookieHistory(callback);
    } else {
        getCookieHistory(callback);
    }
}

export function parseHistory(list, callback) {
    checkIfAuth(
        () => {
            parseServerToHistory(list, callback);
        },
        () => {
            parseStorageToHistory(list, callback);
        }
    );
}

export function parseServerToHistory(list, callback) {
    $.get(`${serverurl}/history`)
        .done(data => {
            if (data.history) {
                parseToHistory(list, data.history, callback);
            }
        })
        .fail((xhr, status, error) => {
            console.error(xhr.responseText);
        });
}

function parseCookieToHistory(list, callback) {
    const notehistory = Cookies.getJSON('notehistory');
    parseToHistory(list, notehistory, callback);
}

export function parseStorageToHistory(list, callback) {
    if (store.enabled) {
        let data = store.get('notehistory');
        if (data) {
            if (typeof data == "string")
                data = JSON.parse(data);
            parseToHistory(list, data, callback);
        } else
            parseCookieToHistory(list, callback);
    } else {
        parseCookieToHistory(list, callback);
    }
}

function parseToHistory(list, notehistory, callback) {
    if (!callback) return;
    else if (!list || !notehistory) callback(list, notehistory);
    else if (notehistory && notehistory.length > 0) {
        for (let i = 0; i < notehistory.length; i++) {
            //parse time to timestamp and fromNow
            const timestamp = (typeof notehistory[i].time === 'number' ? moment(notehistory[i].time) : moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a'));
            notehistory[i].timestamp = timestamp.valueOf();
            notehistory[i].fromNow = timestamp.fromNow();
            notehistory[i].time = timestamp.format('llll');
            // prevent XSS
            notehistory[i].text = S(notehistory[i].text).escapeHTML().s;
            notehistory[i].tags = (notehistory[i].tags && notehistory[i].tags.length > 0) ? S(notehistory[i].tags).escapeHTML().s.split(',') : [];
            // add to list
            if (notehistory[i].id && list.get('id', notehistory[i].id).length == 0)
                list.add(notehistory[i]);
        }
    }
    callback(list, notehistory);
}

export function postHistoryToServer(noteId, data, callback) {
    $.post(`${serverurl}/history/${noteId}`, data)
    .done(result => callback(null, result))
    .fail((xhr, status, error) => {
        console.error(xhr.responseText);
        return callback(error, null);
    });
}

export function deleteServerHistory(noteId, callback) {
    $.ajax({
        url: `${serverurl}/history${noteId ? '/' + noteId : ""}`,
        type: 'DELETE'
    })
    .done(result => callback(null, result))
    .fail((xhr, status, error) => {
        console.error(xhr.responseText);
        return callback(error, null);
    });
}