(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(factory);
    } else if (typeof module === 'object' && typeof module.exports === 'object') {
        factory(require);
    } else {
        // Browser globals
        factory();
    }
}(function () {
    var timeago = function (timestamp) {
        if (timestamp instanceof Date) {
            return inWords(timestamp);
        } else if (typeof timestamp === "string") {
            return inWords(timeago.parse(timestamp));
        } else if (typeof timestamp === "number") {
            return inWords(new Date(timestamp));
        } else {
            return inWords(timeago.datetime(timestamp));
        }
    };

    var settings = {
        refreshMillis: 60000,
        allowPast: true,
        allowFuture: false,
        localeTitle: false,
        cutoff: 1000 * 60 * 60 * 1,
        autoDispose: true,
        strings: {
            prefixAgo: "πριν",
            prefixFromNow: "σε",
            suffixAgo: "",
            suffixFromNow: "",
            seconds: "λιγότερο από ένα λεπτό",
            minute: "περίπου ένα λεπτό",
            minutes: "%d λεπτά",
            hour: 'μία ώρα',
            hours: "%d ώρες",
            day: "μία μέρα",
            days: "%d μέρες",
            month: "περίπου ένα μήνα",
            months: "%d μήνες",
            year: "περίπου ένα χρόνο",
            years: "%d χρόνια",
            wordSeparator: " ",
            numbers: []
        }
    };

    timeago.settings = settings;

    timeago.inWords = function (distanceMillis) {
        if (!settings.allowPast && !settings.allowFuture) {
            throw 'timeago allowPast and allowFuture settings can not both be set to false.';
        }

        var $l = settings.strings;
        var prefix = $l.prefixAgo;
        var suffix = $l.suffixAgo;
        if (settings.allowFuture) {
            if (distanceMillis < 0) {
                prefix = $l.prefixFromNow;
                suffix = $l.suffixFromNow;
            }
        }

        if (!settings.allowPast && distanceMillis >= 0) {
            return settings.strings.inPast;
        }

        var seconds = Math.abs(distanceMillis) / 1000;
        var minutes = seconds / 60;
        var hours = minutes / 60;
        var days = hours / 24;
        var years = days / 365;

        function substitute(stringOrFunction, number) {
            var string = typeof stringOrFunction === 'function' ? stringOrFunction(number, distanceMillis) : stringOrFunction;
            var value = (settings.strings.numbers && settings.strings.numbers[number]) || number;
            return string.replace(/%d/i, value);
        }

        var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
            seconds < 90 && substitute($l.minute, 1) ||
            minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
            minutes < 90 && substitute($l.hour, 1) ||
            hours < 24 && substitute($l.hours, Math.round(hours)) ||
            hours < 42 && substitute($l.day, 1) ||
            days < 30 && substitute($l.days, Math.round(days)) ||
            days < 45 && substitute($l.month, 1) ||
            days < 365 && substitute($l.months, Math.round(days / 30)) ||
            years < 1.5 && substitute($l.year, 1) ||
            substitute($l.years, Math.round(years));

        var separator = $l.wordSeparator || "";
        if ($l.wordSeparator === undefined) { separator = " "; }
        return [prefix, words, suffix].join(separator).trim();
    };

    timeago.parse = function (iso8601) {
        var s = iso8601.trim();
        s = s.replace(/\.\d+/, ""); // remove milliseconds
        s = s.replace(/-/, "/").replace(/-/, "/");
        s = s.replace(/T/, " ").replace(/Z/, " UTC");
        s = s.replace(/([\+\-]\d\d)\:?(\d\d)/, " $1$2"); // -04:00 -> -0400
        s = s.replace(/([\+\-]\d\d)$/, " $100"); // +09 -> +0900
        return new Date(s);
    };

    timeago.datetime = function (elem) {        
        var iso8601 = timeago.isTime(elem) ? elem.getAttribute("datetime") : elem.getAttribute("title");
        return timeago.parse(iso8601);
    };

    timeago.isTime = function (elem) {
        return elem.tagName.toLowerCase() === "time";
    };

    var functions = {
        init: function () {
            functions.dispose.call(this);
            var refreshEl = refresh.bind(this);
            refreshEl();
            if (settings.refreshMillis > 0) {
                this._timeagoInterval = setInterval(refreshEl, settings.refreshMillis);
            }
        },
        update: function (timestamp) {
            var date = timestamp instanceof Date ? timestamp : timeago.parse(timestamp);
            this.dataset.timeago = JSON.stringify({ datetime: date });
            if (settings.localeTitle) {
                this.setAttribute("title", date.toLocaleString());
            }
            refresh.apply(this);
        },
        updateFromDOM: function () {
            var dtv = timeago.isTime(this) ? this.getAttribute("datetime") : this.getAttribute("title");
            console.log(dtv);
            var dt = timeago.parse(dtv);
            this.dataset.timeago = JSON.stringify({ datetime: dt });
            refresh.apply(this);
        },
        dispose: function () {
            if (this._timeagoInterval) {
                clearInterval(this._timeagoInterval);
                this._timeagoInterval = null;
            }
        }
    };

    Object.keys(functions).forEach(function (action) {
        var fn = functions[action];
        if (fn) {
            HTMLElement.prototype[action] = function (options) {
                fn.call(this, options);
            };
        }
    });

    function refresh() {
        if (settings.autoDispose && !document.documentElement.contains(this)) {
            this.dispose();
            return this;
        }

        var data = prepareData(this);
        if (data.datetime) {
            if (settings.cutoff === 0 || Math.abs(distance(data.datetime)) < settings.cutoff) {
                this.innerHTML = inWords(data.datetime);
            } else {
                var title = this.getAttribute('title');
                if (title.length > 0) {
                    this.innerHTML = title;
                }
            }
        }
        return this;
    }

    function prepareData(element) {
        element = element instanceof HTMLElement ? element : this;
        var data = { datetime: null };
        if (!element.dataset.timeago) {
            var dt = timeago.datetime(element);
            data.datetime = dt;
            element.dataset.timeago = JSON.stringify(data);
            var text = element.innerHTML.trim();
            if (settings.localeTitle) {
                element.setAttribute("title", dt.toLocaleString());
            } else if (text.length > 0 && !(timeago.isTime(element) && element.getAttribute("title"))) {
                element.setAttribute("title", text);
            }
        }
        else {
            var d = JSON.parse(element.dataset.timeago);
            data.datetime = new Date(d.datetime);
        }
        return data;
    }

    function inWords(date) {
        return timeago.inWords(distance(date));
    }

    function distance(date) {
        return (new Date().getTime() - date.getTime());
    }

    // fix for IE6 suckage
    document.createElement("abbr");
    document.createElement("time");

    return timeago;
}));

window.initTimeago = function () {
    var timeElms = Array.from(document.querySelectorAll('[data-timeago]'));
    if (timeElms && timeElms.length > 0) {
        timeElms.slice(0, 3).forEach(el => el.init());
        window.addEventListener('load', () => {
            timeElms.slice(3, timeElms.length - 1).forEach(el => el.init());
        });
    }
};
if (document.readyState !== 'loading') {
    window.initTimeago();
} else {
    document.addEventListener('DOMContentLoaded', function () {
        window.initTimeago();
    });
}