require('prismjs/themes/prism.css');
var Prism = require('prismjs');
require('prismjs/components/prism-wiki');
require('prismjs/components/prism-haskell');
require('prismjs/components/prism-go');
require('prismjs/components/prism-typescript');
require('prismjs/components/prism-jsx');
var hljs = require('highlight.js');
var PDFObject = require('pdfobject');
var S = require('string');
var saveAs = require('file-saver').saveAs;
require('../vendor/md-toc');
//auto update last change
window.createtime = null;
window.lastchangetime = null;
window.lastchangeui = {
    status: $(".ui-status-lastchange"),
    time: $(".ui-lastchange"),
    user: $(".ui-lastchangeuser"),
    nouser: $(".ui-no-lastchangeuser")
}
var ownerui = $(".ui-owner");
function updateLastChange() {
    if (!lastchangeui) return;
    if (createtime) {
        if (createtime && !lastchangetime) {
            lastchangeui.status.text('created');
        } else {
            lastchangeui.status.text('changed');
        }
        var time = lastchangetime || createtime;
        lastchangeui.time.html(moment(time).fromNow());
        lastchangeui.time.attr('title', moment(time).format('llll'));
    }
}
setInterval(updateLastChange, 60000);
window.lastchangeuser = null;
window.lastchangeuserprofile = null;
function updateLastChangeUser() {
    if (lastchangeui) {
      if (lastchangeuser && lastchangeuserprofile) {
          var icon = lastchangeui.user.children('i');
          icon.attr('title', lastchangeuserprofile.name).tooltip('fixTitle');
          if (lastchangeuserprofile.photo)
              icon.attr('style', 'background-image:url(' + lastchangeuserprofile.photo + ')');
          lastchangeui.user.show();
          lastchangeui.nouser.hide();
      } else {
          lastchangeui.user.hide();
          lastchangeui.nouser.show();
      }
    }
}
window.owner = null;
window.ownerprofile = null;
function updateOwner() {
    if (ownerui) {
      if (owner && ownerprofile && owner !== lastchangeuser) {
          var icon = ownerui.children('i');
          icon.attr('title', ownerprofile.name).tooltip('fixTitle');
          var styleString = 'background-image:url(' + ownerprofile.photo + ')';
          if (ownerprofile.photo && icon.attr('style') !== styleString)
              icon.attr('style', styleString);
          ownerui.show();
      } else {
          ownerui.hide();
      }
    }
}
//get title
function getTitle(view) {
    var title = "";
    if (md && md.meta && md.meta.title && (typeof md.meta.title == "string" || typeof md.meta.title == "number")) {
        title = md.meta.title;
    } else {
        var h1s = view.find("h1");
        if (h1s.length > 0) {
            title = h1s.first().text();
        } else {
            title = null;
        }
    }
    return title;
}
//render title
function renderTitle(view) {
    var title = getTitle(view);
    if (title) {
        title += ' - HackMD';
    } else {
        title = 'HackMD - Collaborative markdown notes';
    }
    return title;
}
//render filename
function renderFilename(view) {
    var filename = getTitle(view);
    if (!filename) {
        filename = 'Untitled';
    }
    return filename;
}
// render tags
function renderTags(view) {
    var tags = [];
    var rawtags = [];
    if (md && md.meta && md.meta.tags && (typeof md.meta.tags == "string" || typeof md.meta.tags == "number")) {
        var metaTags = ('' + md.meta.tags).split(',');
        for (var i = 0; i < metaTags.length; i++) {
            var text = metaTags[i].trim();
            if (text) rawtags.push(text);
        }
    } else {
        view.find('h6').each(function (key, value) {
            if (/^tags/gmi.test($(value).text())) {
                var codes = $(value).find("code");
                for (var i = 0; i < codes.length; i++) {
                    var text = codes[i].innerHTML.trim();
                    if (text) rawtags.push(text);
                }
            }
        });
    }
    for (var i = 0; i < rawtags.length; i++) {
        var found = false;
        for (var j = 0; j < tags.length; j++) {
            if (tags[j] == rawtags[i]) {
                found = true;
                break;
            }
        }
        if (!found)
            tags.push(rawtags[i]);
    }
    return tags;
}
function slugifyWithUTF8(text) {
    var newText = S(text.toLowerCase()).trim().stripTags().dasherize().s;
    newText = newText.replace(/([\!\"\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\[\\\]\^\`\{\|\}\~])/g, '');
    return newText;
}
function isValidURL(str) {
    var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
        '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
        '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
        '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
        '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
        '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
    if (!pattern.test(str)) {
        return false;
    } else {
        return true;
    }
}
//parse meta
function parseMeta(md, edit, view, toc, tocAffix) {
    var lang = null;
    var dir = null;
    var breaks = true;
    if (md && md.meta) {
        var meta = md.meta;
        lang = meta.lang;
        dir = meta.dir;
        breaks = meta.breaks;
    }
    //text language
    if (lang && typeof lang == "string") {
        view.attr('lang', lang);
        toc.attr('lang', lang);
        tocAffix.attr('lang', lang);
        if (edit)
            edit.attr('lang', lang);
    } else {
        view.removeAttr('lang');
        toc.removeAttr('lang');
        tocAffix.removeAttr('lang');
        if (edit)
            edit.removeAttr('lang', lang);
    }
    //text direction
    if (dir && typeof dir == "string") {
        view.attr('dir', dir);
        toc.attr('dir', dir);
        tocAffix.attr('dir', dir);
    } else {
        view.removeAttr('dir');
        toc.removeAttr('dir');
        tocAffix.removeAttr('dir');
    }
    //breaks
    if (typeof breaks === 'boolean' && !breaks) {
        md.options.breaks = false;
    } else {
        md.options.breaks = true;
    }
}
window.viewAjaxCallback = null;
//regex for extra tags
var spaceregex = /\s*/;
var notinhtmltagregex = /(?![^<]*>|[^<>]*<\/)/;
var coloregex = /\[color=([#|\(|\)|\s|\,|\w]*?)\]/;
coloregex = new RegExp(coloregex.source + notinhtmltagregex.source, "g");
var nameregex = /\[name=(.*?)\]/;
var timeregex = /\[time=([:|,|+|-|\(|\)|\s|\w]*?)\]/;
var nameandtimeregex = new RegExp(nameregex.source + spaceregex.source + timeregex.source + notinhtmltagregex.source, "g");
nameregex = new RegExp(nameregex.source + notinhtmltagregex.source, "g");
timeregex = new RegExp(timeregex.source + notinhtmltagregex.source, "g");
function replaceExtraTags(html) {
    html = html.replace(coloregex, '');
    html = html.replace(nameandtimeregex, ' $1  $2');
    html = html.replace(nameregex, ' $1');
    html = html.replace(timeregex, ' $1');
    return html;
}
if (typeof mermaid !== 'undefined' && mermaid) mermaid.startOnLoad = false;
//dynamic event or object binding here
function finishView(view) {
    //todo list
    var lis = view.find('li.raw').removeClass("raw").sortByDepth().toArray();
    for (var i = 0; i < lis.length; i++) {
        var li = lis[i];
        var html = $(li).clone()[0].innerHTML;
        var p = $(li).children('p');
        if (p.length == 1) {
            html = p.html();
            li = p[0];
        }
        html = replaceExtraTags(html);
        li.innerHTML = html;
        var disabled = 'disabled';
        if(typeof editor !== 'undefined' && havePermission())
            disabled = '';
        if (/^\s*\[[x ]\]\s*/.test(html)) {
            li.innerHTML = html.replace(/^\s*\[ \]\s*/, '')
                .replace(/^\s*\[x\]\s*/, '');
            lis[i].setAttribute('class', 'task-list-item');
        }
        if (typeof editor !== 'undefined' && havePermission())
            $(li).find('input').change(toggleTodoEvent);
        //color tag in list will convert it to tag icon with color
        var tag_color = $(li).closest('ul').find(".color");
        tag_color.each(function (key, value) {
            $(value).addClass('fa fa-tag').css('color', $(value).attr('data-color'));
        });
    }
    //youtube
    view.find("div.youtube.raw").removeClass("raw")
        .click(function () {
            imgPlayiframe(this, '//www.youtube.com/embed/');
        });
    //vimeo
    view.find("div.vimeo.raw").removeClass("raw")
        .click(function () {
            imgPlayiframe(this, '//player.vimeo.com/video/');
        })
        .each(function (key, value) {
            $.ajax({
                type: 'GET',
                url: '//vimeo.com/api/v2/video/' + $(value).attr('data-videoid') + '.json',
                jsonp: 'callback',
                dataType: 'jsonp',
                success: function (data) {
                    var thumbnail_src = data[0].thumbnail_large;
                    var image = '';
                    $(value).prepend(image);
                    if(viewAjaxCallback) viewAjaxCallback();
                }
            });
        });
    //gist
    view.find("code[data-gist-id]").each(function (key, value) {
        if ($(value).children().length == 0)
            $(value).gist(viewAjaxCallback);
    });
    //sequence diagram
    var sequences = view.find("div.sequence-diagram.raw").removeClass("raw");
    sequences.each(function (key, value) {
        try {
            var $value = $(value);
            var $ele = $(value).parent().parent();
            var sequence = $value;
            sequence.sequenceDiagram({
                theme: 'simple'
            });
            $ele.addClass('sequence-diagram');
            $value.children().unwrap().unwrap();
            var svg = $ele.find('> svg');
            svg[0].setAttribute('viewBox', '0 0 ' + svg.attr('width') + ' ' + svg.attr('height'));
            svg[0].setAttribute('preserveAspectRatio', 'xMidYMid meet');
        } catch (err) {
            $value.unwrap();
            console.warn(err);
        }
    });
    //flowchart
    var flow = view.find("div.flow-chart.raw").removeClass("raw");
    flow.each(function (key, value) {
        try {
            var $value = $(value);
            var $ele = $(value).parent().parent();
            var chart = flowchart.parse($value.text());
            $value.html('');
            chart.drawSVG(value, {
                'line-width': 2,
                'fill': 'none',
                'font-size': '16px',
                'font-family': "'Andale Mono', monospace"
            });
            $ele.addClass('flow-chart');
            $value.children().unwrap().unwrap();
        } catch (err) {
            $value.unwrap();
            console.warn(err);
        }
    });
    //graphviz
    var Viz = require("viz.js");
    var graphvizs = view.find("div.graphviz.raw").removeClass("raw");
    graphvizs.each(function (key, value) {
        try {
            var $value = $(value);
            var $ele = $(value).parent().parent();
            var graphviz = Viz($value.text());
            $value.html(graphviz);
            $ele.addClass('graphviz');
            $value.children().unwrap().unwrap();
        } catch (err) {
            $value.unwrap();
            console.warn(err);
        }
    });
    //mermaid
    var mermaids = view.find("div.mermaid.raw").removeClass("raw");
    mermaids.each(function (key, value) {
        try {
            var $value = $(value);
            var $ele = $(value).closest('pre');
            var mermaidError = null;
            mermaid.parseError = function (err, hash) {
                mermaidError = err;
            };
            if (mermaidAPI.parse($value.text())) {
                $ele.addClass('mermaid');
                $ele.html($value.text());
                mermaid.init(undefined, $ele);
            } else {
                $value.unwrap();
                console.warn(mermaidError);
            }
        } catch (err) {
            $value.unwrap();
            console.warn(err);
        }
    });
    //image href new window(emoji not included)
    var images = view.find("img.raw[src]").removeClass("raw");
    images.each(function (key, value) {
        // if it's already wrapped by link, then ignore
        var $value = $(value);
        $value[0].onload = function (e) {
            if(viewAjaxCallback) viewAjaxCallback();
        };
    });
    //blockquote
    var blockquote = view.find("blockquote.raw").removeClass("raw");
    var blockquote_p = blockquote.find("p");
    blockquote_p.each(function (key, value) {
        var html = $(value).html();
        html = replaceExtraTags(html);
        $(value).html(html);
    });
    //color tag in blockquote will change its left border color
    var blockquote_color = blockquote.find(".color");
    blockquote_color.each(function (key, value) {
        $(value).closest("blockquote").css('border-left-color', $(value).attr('data-color'));
    });
    //slideshare
    view.find("div.slideshare.raw").removeClass("raw")
        .each(function (key, value) {
            $.ajax({
                type: 'GET',
                url: '//www.slideshare.net/api/oembed/2?url=http://www.slideshare.net/' + $(value).attr('data-slideshareid') + '&format=json',
                jsonp: 'callback',
                dataType: 'jsonp',
                success: function (data) {
                    var $html = $(data.html);
                    var iframe = $html.closest('iframe');
                    var caption = $html.closest('div');
                    var inner = $('
'
        + highlighted
        + '