Com.Frog.Utils.require(
    '//package/widgets/406C89A82001B4B742762F124D3B000AFC41A14C89829A99/assets/styles/main.css',
    '//package/widgets/406C89A82001B4B742762F124D3B000AFC41A14C89829A99/assets/views/main.ejs',
    '//package/widgets/406C89A82001B4B742762F124D3B000AFC41A14C89829A99/widget.ejs'
).then(function() {
    Com.Frog.Controllers.Widget.extend('Widget.Flashcards', {
    }, {
        prefs: {
            cardset_name: {
                type: "text",
                label: "Give your cards a name",
                defaultValue: ""
            },
            view_mode: {
                type: 'radio',
                label: "Select data entry mode",
                vertical: true,
                options: {
                    'Typed / pasted': 'frog',
                    'Shared Google sheet': 'google'
                },
                defaultValue: "frog",
                publish: []
            },
            card_data_typed: {
                type: "textarea",
                label: "Type / paste your cards here",
                placeholder: "Use a hash tag # to separate the front and back of the cards. Use a semi-colon ; to move onto the next card. e.g. Washington DC#USA;London#UK",
                defaultValue: "",
                hidden: false
            },
            googleurl: {
                type: 'text',
                label: "Shared google sheet link",
                defaultValue: "",
                hidden: false
            },
            card_size: {
                type: 'range',
                label: "Set the size of your cards",
                min: 250,
                max: 600,
                step: 25,
                defaultValue: 250,
                hidden: false,
            },
            select_theme : {
                type: "list",
                label: "Select a theme for your cards",
                defaultValue: "blue",
                options : {
                    "Blue" : "blue",
                    "Green" : "green",
                    "Yellow" : "yellow",
                    "Orange" : "orange",
                    "Red" : "red"
                }
            }
        },

        packageID: '406C89A82001B4B742762F124D3B000AFC41A14C89829A99',
        /**
         * Constructor. Runs when the widget is first loaded.
         *
         * @method init
         */
        init: function() {
            
            !function(a){var b=function(){var a,b=document.createElement("fakeelement"),c={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(a in c)if(void 0!==b.style[a])return c[a]},c=function(b,c,d){this.setting={axis:"y",reverse:!1,trigger:"click",speed:500,forceHeight:!1,forceWidth:!1,autoSize:!0,front:".front",back:".back"},this.setting=a.extend(this.setting,c),"string"!=typeof c.axis||"x"!==c.axis.toLowerCase()&&"y"!==c.axis.toLowerCase()||(this.setting.axis=c.axis.toLowerCase()),"boolean"==typeof c.reverse&&(this.setting.reverse=c.reverse),"string"==typeof c.trigger&&(this.setting.trigger=c.trigger.toLowerCase());var e=parseInt(c.speed);isNaN(e)||(this.setting.speed=e),"boolean"==typeof c.forceHeight&&(this.setting.forceHeight=c.forceHeight),"boolean"==typeof c.forceWidth&&(this.setting.forceWidth=c.forceWidth),"boolean"==typeof c.autoSize&&(this.setting.autoSize=c.autoSize),("string"==typeof c.front||c.front instanceof a)&&(this.setting.front=c.front),("string"==typeof c.back||c.back instanceof a)&&(this.setting.back=c.back),this.element=b,this.frontElement=this.getFrontElement(),this.backElement=this.getBackElement(),this.isFlipped=!1,this.init(d)};a.extend(c.prototype,{flipDone:function(a){var c=this;c.element.one(b(),function(){c.element.trigger("flip:done"),"function"==typeof a&&a.call(c.element)})},flip:function(a){if(!this.isFlipped){this.isFlipped=!0;var b="rotate"+this.setting.axis;this.frontElement.css({transform:b+(this.setting.reverse?"(-180deg)":"(180deg)"),"z-index":"0"}),this.backElement.css({transform:b+"(0deg)","z-index":"1"}),this.flipDone(a)}},unflip:function(a){if(this.isFlipped){this.isFlipped=!1;var b="rotate"+this.setting.axis;this.frontElement.css({transform:b+"(0deg)","z-index":"1"}),this.backElement.css({transform:b+(this.setting.reverse?"(180deg)":"(-180deg)"),"z-index":"0"}),this.flipDone(a)}},getFrontElement:function(){return this.setting.front instanceof a?this.setting.front:this.element.find(this.setting.front)},getBackElement:function(){return this.setting.back instanceof a?this.setting.back:this.element.find(this.setting.back)},init:function(a){var b=this,c=b.frontElement.add(b.backElement),d="rotate"+b.setting.axis,e=2*b.element["outer"+("rotatex"===d?"Height":"Width")](),f={perspective:e,position:"relative"},g={transform:d+"("+(b.setting.reverse?"180deg":"-180deg")+")","z-index":"0",position:"relative"},h={"backface-visibility":"hidden","transform-style":"preserve-3d",position:"absolute","z-index":"1"};b.setting.forceHeight?c.outerHeight(b.element.height()):b.setting.autoSize&&(h.height="100%"),b.setting.forceWidth?c.outerWidth(b.element.width()):b.setting.autoSize&&(h.width="100%"),(window.chrome||window.Intl&&Intl.v8BreakIterator)&&"CSS"in window&&(f["-webkit-transform-style"]="preserve-3d"),c.css(h).find("*").css({"backface-visibility":"hidden"}),b.element.css(f),b.backElement.css(g),setTimeout(function(){var d=b.setting.speed/1e3||.5;c.css({transition:"all "+d+"s ease-out"}),"function"==typeof a&&a.call(b.element)},20),b.attachEvents()},clickHandler:function(b){b||(b=window.event),this.element.find(a(b.target).closest('button, a, input[type="submit"]')).length||(this.isFlipped?this.unflip():this.flip())},hoverHandler:function(){var b=this;b.element.off("mouseleave.flip"),b.flip(),setTimeout(function(){b.element.on("mouseleave.flip",a.proxy(b.unflip,b)),b.element.is(":hover")||b.unflip()},b.setting.speed+150)},attachEvents:function(){var b=this;"click"===b.setting.trigger?b.element.on(a.fn.tap?"tap.flip":"click.flip",a.proxy(b.clickHandler,b)):"hover"===b.setting.trigger&&(b.element.on("mouseenter.flip",a.proxy(b.hoverHandler,b)),b.element.on("mouseleave.flip",a.proxy(b.unflip,b)))},flipChanged:function(a){this.element.trigger("flip:change"),"function"==typeof a&&a.call(this.element)},changeSettings:function(a,b){var c=this,d=!1;if(void 0!==a.axis&&c.setting.axis!==a.axis.toLowerCase()&&(c.setting.axis=a.axis.toLowerCase(),d=!0),void 0!==a.reverse&&c.setting.reverse!==a.reverse&&(c.setting.reverse=a.reverse,d=!0),d){var e=c.frontElement.add(c.backElement),f=e.css(["transition-property","transition-timing-function","transition-duration","transition-delay"]);e.css({transition:"none"});var g="rotate"+c.setting.axis;c.isFlipped?c.frontElement.css({transform:g+(c.setting.reverse?"(-180deg)":"(180deg)"),"z-index":"0"}):c.backElement.css({transform:g+(c.setting.reverse?"(180deg)":"(-180deg)"),"z-index":"0"}),setTimeout(function(){e.css(f),c.flipChanged(b)},0)}else c.flipChanged(b)}}),a.fn.flip=function(b,d){return"function"==typeof b&&(d=b),"string"==typeof b||"boolean"==typeof b?this.each(function(){var c=a(this).data("flip-model");"toggle"===b&&(b=!c.isFlipped),b?c.flip(d):c.unflip(d)}):this.each(function(){if(a(this).data("flip-model")){var e=a(this).data("flip-model");!b||void 0===b.axis&&void 0===b.reverse||e.changeSettings(b,d)}else a(this).data("flip-model",new c(a(this),b||{},d))}),this}}(jQuery);
            
            
            !function(){"use strict";var e=!1;if("undefined"!=typeof process&&!process.browser){e=!0;var t=require("request".trim())}var s=!1,i=!1;try{var n=new XMLHttpRequest;"undefined"!=typeof n.withCredentials?s=!0:"XDomainRequest"in window&&(s=!0,i=!0)}catch(e){}var o=Array.prototype.indexOf,a=function(e,t){var s=0,i=e.length;if(o&&e.indexOf===o)return e.indexOf(t);for(;s<i;s++)if(e[s]===t)return s;return-1},h=function(t){return this&&this instanceof h?("string"==typeof t&&(t={key:t}),this.callback=t.callback,this.wanted=t.wanted||[],this.key=t.key,this.simpleSheet=!!t.simpleSheet,this.parseNumbers=!!t.parseNumbers,this.wait=!!t.wait,this.reverse=!!t.reverse,this.postProcess=t.postProcess,this.debug=!!t.debug,this.query=t.query||"",this.orderby=t.orderby,this.endpoint=t.endpoint||"https://spreadsheets.google.com",this.singleton=!!t.singleton,this.simpleUrl=!(!t.simpleUrl&&!t.simple_url),this.callbackContext=t.callbackContext,this.prettyColumnNames="undefined"==typeof t.prettyColumnNames?!t.proxy:t.prettyColumnNames,"undefined"!=typeof t.proxy&&(this.endpoint=t.proxy.replace(/\/$/,""),this.simpleUrl=!0,this.singleton=!0,s=!1),this.parameterize=t.parameterize||!1,this.singleton&&("undefined"!=typeof h.singleton&&this.log("WARNING! Tabletop singleton already defined"),h.singleton=this),/key=/.test(this.key)&&(this.log("You passed an old Google Docs url as the key! Attempting to parse."),this.key=this.key.match("key=(.*?)(&|#|$)")[1]),/pubhtml/.test(this.key)&&(this.log("You passed a new Google Spreadsheets url as the key! Attempting to parse."),this.key=this.key.match("d\\/(.*?)\\/pubhtml")[1]),/spreadsheets\/d/.test(this.key)&&(this.log("You passed the most recent version of Google Spreadsheets url as the key! Attempting to parse."),this.key=this.key.match("d\\/(.*?)/")[1]),this.key?(this.log("Initializing with key "+this.key),this.models={},this.modelNames=[],this.model_names=this.modelNames,this.baseJsonPath="/feeds/worksheets/"+this.key+"/public/basic?alt=",e||s?this.baseJsonPath+="json":this.baseJsonPath+="json-in-script",void(this.wait||this.fetch())):void this.log("You need to pass Tabletop a key!")):new h(t)};h.callbacks={},h.init=function(e){return new h(e)},h.sheets=function(){this.log("Times have changed! You'll want to use var tabletop = Tabletop.init(...); tabletop.sheets(...); instead of Tabletop.sheets(...)")},h.prototype={fetch:function(e){"undefined"!=typeof e&&(this.callback=e),this.requestData(this.baseJsonPath,this.loadSheets)},requestData:function(t,n){if(this.log("Requesting",t),e)this.serverSideFetch(t,n);else{var o=this.endpoint.split("//").shift()||"http";!s||i&&o!==location.protocol?this.injectScript(t,n):this.xhrFetch(t,n)}},xhrFetch:function(e,t){var s=i?new XDomainRequest:new XMLHttpRequest;s.open("GET",this.endpoint+e);var n=this;s.onload=function(){var e;try{e=JSON.parse(s.responseText)}catch(e){console.error(e)}t.call(n,e)},s.send()},injectScript:function(e,t){var s,i=document.createElement("script");if(this.singleton)t===this.loadSheets?s="Tabletop.singleton.loadSheets":t===this.loadSheet&&(s="Tabletop.singleton.loadSheet");else{var n=this;s="tt"+ +new Date+Math.floor(1e5*Math.random()),h.callbacks[s]=function(){var e=Array.prototype.slice.call(arguments,0);t.apply(n,e),i.parentNode.removeChild(i),delete h.callbacks[s]},s="Tabletop.callbacks."+s}var o=e+"&callback="+s;this.simpleUrl?e.indexOf("/list/")!==-1?i.src=this.endpoint+"/"+this.key+"-"+e.split("/")[4]:i.src=this.endpoint+"/"+this.key:i.src=this.endpoint+o,this.parameterize&&(i.src=this.parameterize+encodeURIComponent(i.src)),this.log("Injecting",i.src),document.getElementsByTagName("script")[0].parentNode.appendChild(i)},serverSideFetch:function(e,s){var i=this;this.log("Fetching",this.endpoint+e),t({url:this.endpoint+e,json:!0},function(e,t,n){return e?console.error(e):void s.call(i,n)})},isWanted:function(e){return 0===this.wanted.length||a(this.wanted,e)!==-1},data:function(){if(0!==this.modelNames.length)return this.simpleSheet?(this.modelNames.length>1&&this.debug&&this.log("WARNING You have more than one sheet but are using simple sheet mode! Don't blame me when something goes wrong."),this.models[this.modelNames[0]].all()):this.models},addWanted:function(e){a(this.wanted,e)===-1&&this.wanted.push(e)},loadSheets:function(t){var i,n,o=[];for(this.googleSheetName=t.feed.title.$t,this.foundSheetNames=[],i=0,n=t.feed.entry.length;i<n;i++)if(this.foundSheetNames.push(t.feed.entry[i].title.$t),this.isWanted(t.feed.entry[i].content.$t)){var a=t.feed.entry[i].link.length-1,h=t.feed.entry[i].link[a].href.split("/").pop(),l="/feeds/list/"+this.key+"/"+h+"/public/values?alt=";l+=e||s?"json":"json-in-script",this.query&&(l+="&tq="+this.query),this.orderby&&(l+="&orderby=column:"+this.orderby.toLowerCase()),this.reverse&&(l+="&reverse=true"),o.push(l)}for(this.sheetsToLoad=o.length,i=0,n=o.length;i<n;i++)this.requestData(o[i],this.loadSheet)},sheets:function(e){return"undefined"==typeof e?this.models:"undefined"==typeof this.models[e]?void 0:this.models[e]},sheetReady:function(e){this.models[e.name]=e,a(this.modelNames,e.name)===-1&&this.modelNames.push(e.name),this.sheetsToLoad--,0===this.sheetsToLoad&&this.doCallback()},loadSheet:function(e){var t=this;new h.Model({data:e,parseNumbers:this.parseNumbers,postProcess:this.postProcess,tabletop:this,prettyColumnNames:this.prettyColumnNames,onReady:function(){t.sheetReady(this)}})},doCallback:function(){0===this.sheetsToLoad&&this.callback.apply(this.callbackContext||this,[this.data(),this])},log:function(){this.debug&&"undefined"!=typeof console&&"undefined"!=typeof console.log&&Function.prototype.apply.apply(console.log,[console,arguments])}},h.Model=function(e){var t,s,i,n;if(this.columnNames=[],this.column_names=this.columnNames,this.name=e.data.feed.title.$t,this.tabletop=e.tabletop,this.elements=[],this.onReady=e.onReady,this.raw=e.data,"undefined"==typeof e.data.feed.entry)return e.tabletop.log("Missing data for "+this.name+", make sure you didn't forget column headers"),this.originalColumns=[],this.elements=[],void this.onReady.call(this);for(var o in e.data.feed.entry[0])/^gsx/.test(o)&&this.columnNames.push(o.replace("gsx$",""));for(this.originalColumns=this.columnNames,this.original_columns=this.originalColumns,t=0,i=e.data.feed.entry.length;t<i;t++){var a=e.data.feed.entry[t],h={};for(s=0,n=this.columnNames.length;s<n;s++){var l=a["gsx$"+this.columnNames[s]];"undefined"!=typeof l?e.parseNumbers&&""!==l.$t&&!isNaN(l.$t)?h[this.columnNames[s]]=+l.$t:h[this.columnNames[s]]=l.$t:h[this.columnNames[s]]=""}void 0===h.rowNumber&&(h.rowNumber=t+1),e.postProcess&&e.postProcess(h),this.elements.push(h)}e.prettyColumnNames?this.fetchPrettyColumns():this.onReady.call(this)},h.Model.prototype={all:function(){return this.elements},fetchPrettyColumns:function(){if(!this.raw.feed.link[3])return this.ready();var e=this.raw.feed.link[3].href.replace("/feeds/list/","/feeds/cells/").replace("https://spreadsheets.google.com",""),t=this;this.tabletop.requestData(e,function(e){t.loadPrettyColumns(e)})},ready:function(){this.onReady.call(this)},loadPrettyColumns:function(e){for(var t={},s=this.columnNames,i=0,n=s.length;i<n;i++)"undefined"!=typeof e.feed.entry[i].content.$t?t[s[i]]=e.feed.entry[i].content.$t:t[s[i]]=s[i];this.prettyColumns=t,this.pretty_columns=this.prettyColumns,this.prettifyElements(),this.ready()},prettifyElements:function(){var e,t,s,i,n=[],o=[];for(t=0,i=this.columnNames.length;t<i;t++)o.push(this.prettyColumns[this.columnNames[t]]);for(e=0,s=this.elements.length;e<s;e++){var a={};for(t=0,i=this.columnNames.length;t<i;t++){var h=this.prettyColumns[this.columnNames[t]];a[h]=this.elements[e][this.columnNames[t]]}n.push(a)}this.elements=n,this.columnNames=o},toArray:function(){var e,t,s,i,n=[];for(e=0,s=this.elements.length;e<s;e++){var o=[];for(t=0,i=this.columnNames.length;t<i;t++)o.push(this.elements[e][this.columnNames[t]]);n.push(o)}return n}},"undefined"!=typeof module&&module.exports?module.exports=h:"function"==typeof define&&define.amd?define(function(){return h}):window.Tabletop=h}();
            
            
        },

        /**
         * Event fired by the Site Controller.
         *
         * @event 'widget.live'
         */
        'widget.live': function(el, ev, data) {
            this.element.html(
                this.view('main.ejs')
            );
            
            var card_set_name = this.prefs.cardset_name.value;
            var card_no = 1;
            var lastRandom;
            var publicSpreadsheetUrl;
            var str = this.prefs.card_data_typed.value;
            var card_array;
            var arrayLength;
            var google = false;
            var themes = {
                blue:{frbg:'#1189d1',babg:'#052c44',brbc:'#86cbf5'},
                green:{frbg:'#18b755',babg:'#063016',brbc:'#7aeea'},
                yellow:{frbg:'#f3b50b',babg:'#614804',brbc:'#fbe19c'},
                orange:{frbg:'#ef4809',babg:'#5c1c03',brbc:'#fbb296'},
                red:{frbg:'#e82c0c',babg:'#571004',brbc:'#f9a294'}
            };
            var LoadCard = function(cmd) {
                if (cmd === "first") {
                    var card = card_array[0].split("#");
                    this.element.find(".front").html("<p>"+card[0]+"</p>");
                    this.element.find(".back").html("<p>"+card[1]+"</p>");
                    this.element.find("[data-name='random']").html("1 / "+arrayLength);
                }
                if (cmd === "next") {
                    var card = card_array[(card_no-1)].split("#");
                    this.element.find(".front").html("<p>"+card[0]+"</p>");
                    this.element.find(".back").html("<p>"+card[1]+"</p>");
                    this.element.find("[data-name='random']").html(card_no+" / "+arrayLength);
                }
                if (cmd === "random") {
                    var random_card = getRandomInt(0, (arrayLength-1));
                    var card = card_array[random_card].split("#");
                    this.element.find(".front").html("<p>"+card[0]+"</p>");
                    this.element.find(".back").html("<p>"+card[1]+"</p>");
                    this.element.find("[data-name='random']").html((random_card+1)+" / "+arrayLength);
                    card_no = random_card + 1;
                }
                lastRandom = card_no - 1;
            }.bind(this);
            var initCards = function(card_config) {
            //function initCards(card_config) {
                if (card_config.length > 0) {
                    card_array = card_config.split(";");
                    arrayLength = card_array.length;
                    LoadCard("first");
                } else {
                    this.element.find(".front").html("<p>"+card_set_name + " cards not found!</p>");
                }
            }.bind(this);
            
            

            //example url https://docs.google.com/spreadsheets/d/1nmmf-46WO7Mi-_EOb5rIRGZyfMA9VB4BZYfMFttOjBM/edit?usp=sharing
            if (this.prefs.view_mode.value == "google") {
                google = true;
                if (this.prefs.googleurl.value == '') {
                    publicSpreadsheetUrl = "!";
                } else {
                    publicSpreadsheetUrl = this.prefs.googleurl.value;
                }
            }

            this.element.find(".nav").width(this.prefs.card_size.value);
            this.element.find("[data-name='card']").width(this.prefs.card_size.value);
            this.element.find("[data-name='card']").height(this.prefs.card_size.value/1.8);
            this.element.find(".front").html("<p>Looking for " + card_set_name + " cards...</p>");
            this.element.find(".front").css('background-color', themes[this.prefs.select_theme.value].frbg);
            this.element.find(".back").css('background-color', themes[this.prefs.select_theme.value].babg);
            this.element.find(".back").css('border-color', themes[this.prefs.select_theme.value].brbc);
            this.element.find(".btnx").css('background-color', themes[this.prefs.select_theme.value].frbg);
            this.element.find(".btnx").css('border-color', themes[this.prefs.select_theme.value].brbc);

            if (str.substr(-1) === ";") {
                str = str.slice(0, -1);
            }

            if (google) {
                $.get(publicSpreadsheetUrl).done(function () {
                    this.element.find(".front").html("<p>Loading Google sheet...</p>");
                    Tabletop.init( { key: publicSpreadsheetUrl,
                                    callback: loadSheet,
                                    simpleSheet: true } )
                }.bind(this)).fail(function () {
                    this.element.find(".front").html("<p>Google sheet not found!</p>");
                }.bind(this));
            } else {
                initCards(str);
            }

            this.element.find("[data-name='card']").flip({
                autoSize:false
            });
            this.element.find("[data-name='random']").click(function() {
                LoadCard("random");
            });
            this.element.find("[data-name='next']").click(function() {
                card_no = card_no + 1;
                if (card_no > arrayLength) {
                    card_no = arrayLength;
                }
                LoadCard("next");
            });
            this.element.find("[data-name='prev']").click(function() {
                card_no = card_no - 1;
                if (card_no < 1) {
                    card_no = 1;
                }
                LoadCard("next");
            });

            function getRandomInt(min, max) {
                var random = Math.floor(Math.random() * (max - min + 1)) + min;
                if (lastRandom !== undefined) {
                    if (random == lastRandom) {
                        random = random + 1;
                    }
                    if (random > max) {
                        random = random - 2;
                    }
                }
                lastRandom = random;
                return random;
            }

            function loadSheet(data, tabletop) {
                var mystr = "";
                for (var key in data) {
                    if (data.hasOwnProperty(key)) {
                        var thisRow = "";
                        for (var key2 in data[key]) {
                            if (data[key].hasOwnProperty(key2)) {
                                thisRow = thisRow + data[key][key2] + "#";
                            }
                        }
                        thisRow = thisRow.slice(0, -1);
                        mystr = mystr + thisRow + ";";
                    }
                }
                mystr = mystr.slice(0,-1);
                initCards(mystr);
            }

        },

        /**
         * Event fired by the Site Controller. Tells the widget that the site is in Edit Mode.
         *
         * @event 'widget.edit'
         */
        'widget.edit': function(el, ev, data) {
            this.element.html(
                this.view('./widget.ejs')
            );
        },

        /**
         * Event fired by the Site Controller. Tells the widget that something has been changed during editing.
         *
         * @event 'widget.updated'
         */
        'widget.updated': function(el, ev, data) {}
    });
});
