/**
 * @license
 *
 * Copyright (c) 2015, University of Washington Interactive Data Lab.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the University of Washington Interactive Data Lab
 *   nor the names of its contributors may be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
"use strict";angular.module("polestar",["vlui","ngSanitize","ngTouch","ngDragDrop","zeroclipboard","Chronicle","LocalStorageModule","720kb.tooltips","ngOrderObjectBy","angular-google-analytics"]).constant("_",window._).constant("vl",window.vl).constant("vg",window.vg).constant("ZSchema",window.ZSchema).constant("Tether",window.Tether).constant("Drop",window.Drop).constant("Blob",window.Blob).constant("URL",window.URL).constant("jsondiffpatch",window.jsondiffpatch).config(["consts",function(e){window.vg.util.extend(e,{appId:"polestar",initialSpec:window.initialSpec||void 0,logToWebSql:!1})}]).config(["vl",function(e){e.config.defaultConfig.countTitle="COUNT"}]).config(["uiZeroclipConfigProvider",function(e){e.setZcConf({swfPath:"bower_components/zeroclipboard/dist/ZeroClipboard.swf"})}]).config(["localStorageServiceProvider",function(e){e.setPrefix("polestar")}]).decorator("Dataset",["$q","vg","$delegate",function(e,a,t){var o=t.update;return t.getUpdate=function(t,n){return t.url?e(function(e,o){a.util.load({url:t.url},function(e,a){e?console.log(e):n(t,a)}),e()}):o(t)},t}]),angular.module("polestar").directive("vlSpecEditor",["Spec",function(e){return{templateUrl:"components/vlSpecEditor/vlSpecEditor.html",restrict:"E",scope:{},link:function(a){a.Spec=e,a.parseShorthand=e.parseShorthand,a.parseVegalite=function(a){e.reset(JSON.parse(a))}}}}]),angular.module("polestar").directive("vgSpecEditor",["Spec",function(e){return{templateUrl:"components/vgSpecEditor/vgSpecEditor.html",restrict:"E",scope:{},link:function(a){a.Spec=e}}}]),angular.module("polestar").directive("nullFilterDirective",["Spec",function(e){return{templateUrl:"components/nullfilterdirective/nullfilterdirective.html",restrict:"E",scope:{},link:function(a,t,o){a.Spec=e,a.updateFilter=function(){e.update()}}}}]),angular.module("polestar").directive("lyraExport",function(){return{template:'<a href="#" class="command" ng-click="export()">Export to lyra</a>',restrict:"E",replace:!0,scope:{},controller:["$scope","$timeout","Spec","Alerts",function(e,a,t,o){e["export"]=function(){var e=t.vgSpec;e||o.add("No vega spec present."),e.marks[0]["lyra.groupType"]="layer";var n="http://idl.cs.washington.edu/projects/lyra/app/",i=window.open(n,"_blank");a(function(){o.add("Please check whether lyra loaded the vega spec correctly. This feature is experimental and may not work.",5e3),i.postMessage({spec:e},n)},5e3)}}]}}),angular.module("polestar").directive("jsonInput",["JSON3",function(e){return{restrict:"A",require:"ngModel",scope:{},link:function(a,t,o,n){var i=function(a){return e.stringify(a,null,"  ",80)};n.$formatters.push(i)}}}]),angular.module("polestar").directive("configurationEditor",function(){return{templateUrl:"components/configurationeditor/configurationeditor.html",restrict:"E",scope:{},controller:["$scope","Config",function(e,a){e.Config=a}]}}),angular.module("polestar").service("Spec",["_","vg","vl","ZSchema","Alerts","Config","Dataset","Schema","Pills","consts",function(e,a,t,o,n,i,s,c,r,d){function l(t){for(var o in t)e.isObject(t[o])&&l(t[o]),(null===t[o]||void 0===t[o]||e.isObject(t[o])&&0===a.util.keys(t[o]).length&&"bin"!==o||t[o]===[])&&delete t[o]}function p(e){return{}}function g(e,a,o){var n=a.type,i=t.channel.getSupportedRole(o),s=i.dimension&&!i.measure;a.field&&s?"count"===a.aggregate?a={}:n!==t.type.QUANTITATIVE||a.bin?n!==t.type.TEMPORAL||a.timeUnit||(a.timeUnit=d.defaultTimeFn):(a.aggregate=void 0,a.bin={maxbins:t.bin.MAXBINS_DEFAULT}):a.field||(a={});var r=p(o),l=c.getChannelSchema(o).properties;for(var g in l)a[g]&&("value"===g&&a.field?delete r[g]:r[g]=a[g]);e[o]=r}var u={spec:null,chart:{vlSpec:null,encoding:null,shorthand:null,vgSpec:null}};return u._removeEmptyFieldDefs=function(a){a.encoding=e.omit(a.encoding,function(e,o){return!e||void 0===e.field&&void 0===e.value||a.mark&&!t.channel.supportMark(o,a.mark)})},u.parseShorthand=function(e){var a=t.shorthand.parseShorthand(e,null,i.config);u.reset(a)},u.reset=function(a){var o={data:i.data,mark:"point",encoding:e.keys(c.schema.definitions.Encoding.properties).reduce(function(e,a){return e[a]={},e},{}),config:i.config};a&&(o=t.util.mergeDeep(o,a)),u.spec=o},u.update=function(s){s=e.cloneDeep(s||u.spec),u._removeEmptyFieldDefs(s),l(s),"encoding"in s||(s.encoding={}),"config"in s||(s.config={});var r=new o;r.setRemoteReference("http://json-schema.org/draft-04/schema",{});var d=c.schema;o.registerFormat("color",function(e){return/^#([0-9a-f]{3}){1,2}$/i.test(e)}),o.registerFormat("font",function(){return!1});var p=r.validate(s,d);if(p){a.util.extend(s.config,i.large());var g=u.chart;g.fieldSet=u.spec.encoding,g.vlSpec=s,g.cleanSpec=s,g.shorthand=t.shorthand.shorten(s)}else n.add({msg:r.getLastErrors()})},r.listener={set:function(e,a){g(u.spec.encoding,a,e)},remove:function(e){g(u.spec.encoding,{},e)},update:function(e){u.update(e)},reset:function(){u.reset()},dragDrop:function(a,t){var o=e.clone(u.spec.encoding);t&&g(o,r.get(t)||{},t),g(o,r.get(a)||{},a),u.spec.encoding=o}},u.reset(),s.onUpdate.push(u.reset),u}]),angular.module("polestar").controller("MainCtrl",["$scope","$document","Spec","Dataset","Config","consts","Chronicle","Logger","Bookmarks","Modals",function(e,a,t,o,n,i,s,c,r,d){e.Spec=t,e.Dataset=o,e.Config=n,e.Logger=c,e.Bookmarks=r,e.consts=i,e.showDevPanel=!1,e.embedded=!!i.embeddedData,e.canUndo=!1,e.canRedo=!1,e.showModal=function(e){d.open(e),"bookmark-list"==e&&c.logInteraction(c.actions.BOOKMARK_OPEN)},r.isSupported&&r.load(),e.embedded&&(o.dataset={values:i.embeddedData,name:"embedded"}),o.update(o.dataset).then(function(){n.updateDataset(o.dataset),i.initialSpec&&t.reset(i.initialSpec),e.chron=s.record("Spec.spec",e,!0,["Dataset.dataset","Dataset.dataschema","Dataset.stats","Config.config"]),e.canUndoRedo=function(){e.canUndo=e.chron.canUndo(),e.canRedo=e.chron.canRedo()},e.chron.addOnAdjustFunction(e.canUndoRedo),e.chron.addOnUndoFunction(e.canUndoRedo),e.chron.addOnRedoFunction(e.canUndoRedo),e.chron.addOnUndoFunction(function(){c.logInteraction(c.actions.UNDO)}),e.chron.addOnRedoFunction(function(){c.logInteraction(c.actions.REDO)}),angular.element(a).on("keydown",function(a){return a.keyCode!=="Z".charCodeAt(0)||!a.ctrlKey&&!a.metaKey||a.shiftKey?a.keyCode==="Y".charCodeAt(0)&&(a.ctrlKey||a.metaKey)?(e.chron.redo(),e.$digest(),!1):a.keyCode==="Z".charCodeAt(0)&&(a.ctrlKey||a.metaKey)&&a.shiftKey?(e.chron.redo(),e.$digest(),!1):void 0:(e.chron.undo(),e.$digest(),!1)})})}]),angular.module("polestar").controller("MainCtrlEmbed",["$scope","$document","Spec","Dataset","Config","consts","Chronicle","Logger","Bookmarks","Modals",function(e,a,t,o,n,i,s,c,r,d){e.Spec=t,e.Dataset=o,e.Config=n,e.Logger=c,e.Bookmarks=r,e.consts=i,e.showDevPanel=!1,e.embedded=!!i.embeddedData,e.canUndo=!1,e.canRedo=!1,e.showModal=function(e){d.open(e),"bookmark-list"==e&&c.logInteraction(c.actions.BOOKMARK_OPEN)},r.isSupported&&r.load(),e.embedded&&(i.embeddedData._directEmbed?o.dataset=i.embeddedData:o.dataset={values:i.embeddedData,name:"embedded"}),o.update(o.dataset).then(function(){n.updateDataset(o.dataset),i.initialSpec&&t.reset(i.initialSpec),e.chron=s.record("Spec.spec",e,!0,["Dataset.dataset","Dataset.dataschema","Dataset.stats","Config.config"]),e.canUndoRedo=function(){e.canUndo=e.chron.canUndo(),e.canRedo=e.chron.canRedo()},e.chron.addOnAdjustFunction(e.canUndoRedo),e.chron.addOnUndoFunction(e.canUndoRedo),e.chron.addOnRedoFunction(e.canUndoRedo),e.chron.addOnUndoFunction(function(){c.logInteraction(c.actions.UNDO)}),e.chron.addOnRedoFunction(function(){c.logInteraction(c.actions.REDO)}),angular.element(a).on("keydown",function(a){return a.keyCode!=="Z".charCodeAt(0)||!a.ctrlKey&&!a.metaKey||a.shiftKey?a.keyCode==="Y".charCodeAt(0)&&(a.ctrlKey||a.metaKey)?(e.chron.redo(),e.$digest(),!1):a.keyCode==="Z".charCodeAt(0)&&(a.ctrlKey||a.metaKey)&&a.shiftKey?(e.chron.redo(),e.$digest(),!1):void 0:(e.chron.undo(),e.$digest(),!1)})})}]),angular.module("polestar").run(["$templateCache",function(e){e.put("components/nullfilterdirective/nullfilterdirective.html",'<label><input ng-model="Spec.spec.config.filterNull.O" ng-change="updateFilter()" type="checkbox"> Remove null values</label>'),e.put("components/configurationeditor/configurationeditor.html","<form><pre>{{ Config.config | compactJSON }}</pre></form>"),e.put("components/vgSpecEditor/vgSpecEditor.html",'<div class="card scroll-y abs-100 vflex no-right-margin"><div><div class="right"><a class="command" ui-zeroclip="" zeroclip-model="Spec.chart.vgSpec | compactJSON">Copy</a><lyra-export></lyra-export></div><h3>Vega Specification</h3></div><textarea class="vgspec flex-grow-1" json-input="" type="text" ng-model="Spec.chart.vgSpec"></textarea></div>'),e.put("components/vlSpecEditor/vlSpecEditor.html",'<div class="card scroll-y abs-100 vflex"><div class="subpane no-shrink"><a ng-click="parseShorthand(Spec.chart.shorthand)" class="right command">Load</a><div class="right command"><a ui-zeroclip="" zeroclip-model="Spec.chart.shorthand">Copy</a></div><h3>Vega-Lite Shorthand</h3><input class="shorthand full-width" type="text" ng-model="Spec.chart.shorthand"></div><div class="subpane flex-grow-1 vflex"><div><a ng-click="parseVegalite(Spec.chart.vlSpec)" class="right command">Load</a><div class="right command"><a ui-zeroclip="" zeroclip-model="Spec.chart.cleanSpec | compactJSON">Copy</a></div><h3>Vega-Lite Encoding</h3></div><textarea class="vlspec flex-grow-1 full-height" json-input="" type="text" ng-model="Spec.chart.cleanSpec"></textarea></div></div>'),e.put("app/main/main-embed.html",'<div ng-controller="MainCtrlEmbed" class="flex-root vflex full-width full-height"><div class="full-width no-shrink"><div class="card top-card no-right-margin no-top-margin"><div class="hflex"><div id="logo"></div><div class="pane"><div class="controls"><a ng-show="Bookmarks.isSupported" class="command" ng-click="showModal(\'bookmark-list\')"><i class="fa fa-bookmark"></i> Bookmarks ({{Bookmarks.list.length}})</a> <a class="command" ng-click="chron.undo()" ng-class="{disabled: !canUndo}"><i class="fa fa-undo"></i> Undo</a> <a class="command" ng-click="chron.redo()" ng-class="{disabled: !canRedo}"><i class="fa fa-repeat"></i> Redo</a> <a class="command" ng-click="showExportPanel = !showExportPanel" ng-class="{disabled: !canUndo}"><i class="fa fa-repeat"></i> Export</a></div></div><div class="absolute-top-right"><a href="https://idl.cs.washington.edu/" target="_blank" class="idl-logo"></a></div></div></div><alert-messages></alert-messages></div><div class="hflex full-width main-panel grow-1"><div class="pane data-pane noselect"><div class="card no-top-margin data-card abs-100"><div class="sidebar-header" ng-if="!embedded"><h2>Data</h2><dataset-selector class="right"></dataset-selector><div class="current-dataset" title="{{Dataset.currentDataset.name}}"><i class="fa fa-database"></i> <span class="dataset-name">{{Dataset.currentDataset.name}}</span></div></div><schema-list field-defs="Dataset.dataschema" order-by="Dataset.fieldOrder"></schema-list><div id="footer"><ul class="menu"><span ng-show="consts.debug"></span></ul></div></div></div><div class="pane encoding-pane"><shelves spec="Spec.spec"></shelves></div><div class="pane vis-pane"><vl-plot-group class="card abs-100 no-top-margin no-right-margin full-vl-plot-group" chart="Spec.chart" show-bookmark="true" show-filter-null="true" show-log="true" show-mark-type="true" show-sort="true" show-transpose="true" config-set="large" show-label="true" tooltip="true" always-scrollable="true"></vl-plot-group></div></div><div class="hflex full-width dev-panel" ng-if="showDevPanel"><div class="pane" ng-show="consts.logToWebSql"><div class="card"><div>userid: {{Logger.userid}}</div><button ng-click="Logger.clear()">Clear logs</button><br><button ng-click="Logger.export()">Download logs</button></div></div><div class="pane config-pane"><div class="card scroll-y abs-100"><configuration-editor></configuration-editor></div></div><div class="pane vl-pane"><vl-spec-editor></vl-spec-editor></div><div class="pane vg-pane"><vg-spec-editor></vg-spec-editor></div></div><div class="hflex full-width dev-panel" ng-if="showExportPanel"><div class="pane vg-pane"><vg-spec-editor></vg-spec-editor></div></div><bookmark-list highlighted="Fields.highlighted"></bookmark-list><dataset-modal></dataset-modal></div>'),e.put("app/main/main.html",'<div ng-controller="MainCtrl" class="flex-root vflex full-width full-height"><div class="full-width no-shrink"><div class="card top-card no-right-margin no-top-margin"><div class="hflex"><div id="logo"></div><div class="pane"><div class="controls"><a ng-show="Bookmarks.isSupported" class="command" ng-click="showModal(\'bookmark-list\')"><i class="fa fa-bookmark"></i> Bookmarks ({{Bookmarks.list.length}})</a> <a class="command" ng-click="chron.undo()" ng-class="{disabled: !canUndo}"><i class="fa fa-undo"></i> Undo</a> <a class="command" ng-click="chron.redo()" ng-class="{disabled: !canRedo}"><i class="fa fa-repeat"></i> Redo</a></div></div><div class="absolute-top-right"><a href="https://idl.cs.washington.edu/" target="_blank" class="idl-logo"></a></div></div></div><alert-messages></alert-messages></div><div class="hflex full-width main-panel grow-1"><div class="pane data-pane noselect"><div class="card no-top-margin data-card abs-100"><div class="sidebar-header" ng-if="!embedded"><h2>Data</h2><dataset-selector class="right"></dataset-selector><div class="current-dataset" title="{{Dataset.currentDataset.name}}"><i class="fa fa-database"></i> <span class="dataset-name">{{Dataset.currentDataset.name}}</span></div></div><schema-list field-defs="Dataset.dataschema" order-by="Dataset.fieldOrder"></schema-list><div id="footer"><ul class="menu"><span ng-show="consts.debug"><li><a class="debug" ng-click="showDevPanel = !showDevPanel">Debug</a></li><li><a ng-href="{{ {spec:Spec.chart.vlSpec} | reportUrl }}" target="_blank" class="debug">Report an issue</a></li></span></ul></div></div></div><div class="pane encoding-pane"><shelves spec="Spec.spec"></shelves></div><div class="pane vis-pane"><vl-plot-group class="card abs-100 no-top-margin no-right-margin full-vl-plot-group" chart="Spec.chart" show-bookmark="true" show-filter-null="true" show-log="true" show-mark-type="true" show-sort="true" show-transpose="true" config-set="large" show-label="true" tooltip="true" always-scrollable="true"></vl-plot-group></div></div><div class="hflex full-width dev-panel" ng-if="showDevPanel"><div class="pane" ng-show="consts.logToWebSql"><div class="card"><div>userid: {{Logger.userid}}</div><button ng-click="Logger.clear()">Clear logs</button><br><button ng-click="Logger.export()">Download logs</button></div></div><div class="pane config-pane"><div class="card scroll-y abs-100"><configuration-editor></configuration-editor></div></div><div class="pane vl-pane"><vl-spec-editor></vl-spec-editor></div><div class="pane vg-pane"><vg-spec-editor></vg-spec-editor></div></div><bookmark-list highlighted="Fields.highlighted"></bookmark-list><dataset-modal></dataset-modal></div>')}]);