let app;

function loadVue() {
	// data = a function returning the content (actually HTML)
	Vue.component("display-text", {
		props: ["layer", "data"],
		template: `
          <span class="instant" v-html="data"></span>
		`
	});

	// data = a function returning the content (actually HTML)
	Vue.component("raw-html", {
		props: ["layer", "data"],
		template: `
          <span class="instant" v-html="data"></span>
		`
	});

	// Blank space, data = optional height in px or pair with width and height in px
	Vue.component("blank", {
		props: ["layer", "data"],
		template: `
          <div class="instant">
          <div class="instant" v-if="!data" v-bind:style="{'width': '8px', 'height': '17px'}"></div>
          <div class="instant" v-else-if="Array.isArray(data)"
               v-bind:style="{'width': data[0], 'height': data[1]}"></div>
          <div class="instant" v-else v-bind:style="{'width': '8px', 'height': data}"><br></div>
          </div>
		`
	});

	// Displays an image, data is the URL
	Vue.component("display-image", {
		props: ["layer", "data"],
		template: `
          <img class="instant" v-bind:src="data" v-bind:alt="data">
		`
	});

	// data = an array of Components to be displayed in a row
	Vue.component("row", {
		props: ["layer", "data"],
		computed: {
			key() {
				return this.$vnode.key;
			}
		},
		template: `
          <div class="upgTable instant">
          <div class="upgRow">
            <div v-for="(item, index) in data">
              <div v-if="!Array.isArray(item)" v-bind:is="item" :layer="layer"
                   v-bind:style="tmp[layer].componentStyles[item]" :key="key + '-' + index"></div>
              <div v-else-if="item.length===3"
                   v-bind:style="[tmp[layer].componentStyles[item[0]], (item[2] ? item[2] : {})]" v-bind:is="item[0]"
                   :layer="layer" :data="item[1]" :key="key + '-' + index"></div>
              <div v-else-if="item.length===2" v-bind:is="item[0]" :layer="layer" :data="item[1]"
                   v-bind:style="tmp[layer].componentStyles[item[0]]" :key="key + '-' + index"></div>
            </div>
          </div>
          </div>
		`
	});

	// data = an array of Components to be displayed in a column
	Vue.component("column", {
		props: ["layer", "data"],
		computed: {
			key() {
				return this.$vnode.key;
			}
		},
		template: `
          <div class="upgTable instant">
          <div class="upgCol">
            <template v-for="(item, index) in data">
              <div v-if="!Array.isArray(item)" v-bind:is="item" :layer="layer"
                   v-bind:style="tmp[layer].componentStyles[item]" :key="key + '-' + index"></div>
              <div v-else-if="item.length===3"
                   v-bind:style="[tmp[layer].componentStyles[item[0]], (item[2] ? item[2] : {})]" v-bind:is="item[0]"
                   :layer="layer" :data="item[1]" :key="key + '-' + index"></div>
              <div v-else-if="item.length===2" v-bind:is="item[0]" :layer="layer" :data="item[1]"
                   v-bind:style="tmp[layer].componentStyles[item[0]]" :key="key + '-' + index"></div>
            </template>
          </div>
          </div>
		`
	});

	// data [other layer, tabformat for within proxy]
	Vue.component('layer-proxy', {
		props: ['layer', 'data'],
		computed: {
			key() {return this.$vnode.key}
		},
		template: `
		<div>
			<column :layer="data[0]" :data="data[1]" :key="key + 'col'"></column>
		</div>
		`
	})

	Vue.component("infobox", {
		props: ["layer", "data"],
		template: `
          <div v-bind:class="{ story: true, instant: true, closed: player.infoboxes[layer][data] }"
               v-if="tmp[layer].infoboxes && tmp[layer].infoboxes[data]!== undefined && tmp[layer].infoboxes[data].unlocked"
               v-bind:style="[{'border-color': tmp[layer].color}, tmp[layer].infoboxes[data].style]">
          <button class="story-title instant"
                  v-bind:style="[{'background-color': tmp[layer].color}, tmp[layer].infoboxes[data].titleStyle]"
                  v-on:click="player.infoboxes[layer][data] = !player.infoboxes[layer][data]">
            <span class="story-toggle">{{ player.infoboxes[layer][data] ? "+" : "-" }}</span>
            <span
                v-html="tmp[layer].infoboxes[data].title ? tmp[layer].infoboxes[data].title : (tmp[layer].name)"></span>
          </button>
          <div class="story-text instant" v-bind:style="tmp[layer].infoboxes[data].bodyStyle">
            <span v-html="tmp[layer].infoboxes[data].body ? tmp[layer].infoboxes[data].body : 'Blah'"></span>
          </div>
          </div>
		`
	});


	// Data = width in px, by default fills the full area
	Vue.component("h-line", {
		props: ["layer", "data"],
		template: `
          <hr class="instant" v-bind:style="data ? {'width': data} : {}" class="hl">
		`
	});

	// Data = height in px, by default is bad
	Vue.component("v-line", {
		props: ["layer", "data"],
		template: `
          <div class="instant" v-bind:style="data ? {'height': data} : {}" class="vl2"></div>
		`
	});

	Vue.component("challenges", {
		props: ["layer"],
		template: `
          <div v-if="tmp[layer].challenges" class="upgTable">
          <div v-for="row in tmp[layer].challenges.rows" class="upgRow">
            <div v-for="col in tmp[layer].challenges.cols">
              <challenge
                  v-if="tmp[layer].challenges[row*10+col]!== undefined && tmp[layer].challenges[row*10+col].unlocked"
                  :layer="layer" :data="row*10+col" v-bind:style="tmp[layer].componentStyles.challenge"></challenge>
            </div>
          </div>
          </div>
		`
	});

	// data = id
	Vue.component('challenge', {
		props: ['layer', 'data'],
		template: `
		<div v-if="tmp[layer].challenges && tmp[layer].challenges[data]!== undefined && tmp[layer].challenges[data].unlocked && !(player.hideChallenges && maxedChallenge(layer, [data]))"
			v-bind:class="['hChallenge', challengeStyle(layer, data)]" v-bind:style="tmp[layer].challenges[data].style">
			<br><h3 v-html="tmp[layer].challenges[data].name"></h3><br><br>
			<button v-bind:class="{ longUpg: true, can: true, [layer]: true }" v-bind:style="{'background-color': tmp[layer].color}" v-on:click="startChallenge(layer, data)">{{challengeButtonText(layer, data)}}</button><br><br>
			<span v-if="layers[layer].challenges[data].fullDisplay" v-html="run(layers[layer].challenges[data].fullDisplay, layers[layer].challenges[data])"></span>
			<span v-else>
				<span v-html="tmp[layer].challenges[data].challengeDescription"></span><br>
				Goal:  <span v-if="tmp[layer].challenges[data].goalDescription"
                             v-html="tmp[layer].challenges[data].goalDescription"></span><span
              v-else>{{ format(tmp[layer].challenges[data].goal) }}
            {{ tmp[layer].challenges[data].currencyDisplayName ? tmp[layer].challenges[data].currencyDisplayName : "points" }}</span><br>
				Reward: <span v-html="tmp[layer].challenges[data].rewardDescription"></span><br>
				<span v-if="layers[layer].challenges[data].rewardDisplay!==undefined">Currently: <span v-html="(tmp[layer].challenges[data].rewardDisplay) ? (run(layers[layer].challenges[data].rewardDisplay, layers[layer].challenges[data])) : format(tmp[layer].challenges[data].rewardEffect)"></span></span>
			</span>
			<node-mark :layer='layer' :data='tmp[layer].challenges[data].marked' :offset="10"></node-mark></span>

		</div>
		`
	});

	Vue.component("upgrades", {
		props: ["layer", "data"],
		template: `
          <div v-if="tmp[layer].upgrades" class="upgTable">
          <div v-for="row in (data === undefined ? tmp[layer].upgrades.rows : data)" class="upgRow">
            <div v-for="col in tmp[layer].upgrades.cols">
              <div v-if="tmp[layer].upgrades[row*10+col]!== undefined && tmp[layer].upgrades[row*10+col].unlocked"
                   class="upgAlign">
                <upgrade :layer="layer" :data="row*10+col" v-bind:style="tmp[layer].componentStyles.upgrade"></upgrade>
              </div>
            </div>
          </div>
          <br>
          </div>
		`
	});

	// data = id
	Vue.component("upgrade", {
		props: ["layer", "data"],
		template: `
          <button
              v-if="tmp[layer].upgrades && tmp[layer].upgrades[data]!== undefined && tmp[layer].upgrades[data].unlocked"
              v-on:click="buyUpg(layer, data)"
              v-bind:class="{ [layer]: true, upg: true, bought: hasUpgrade(layer, data), locked: (!(canAffordUpgrade(layer, data))&&!hasUpgrade(layer, data)), can: (canAffordUpgrade(layer, data)&&!hasUpgrade(layer, data))}"
              v-bind:style="[((!hasUpgrade(layer, data) && canAffordUpgrade(layer, data)) ? {'background-color': tmp[layer].color} : {}), tmp[layer].upgrades[data].style]">
          <span v-if="layers[layer].upgrades[data].fullDisplay" v-html="run(layers[layer].upgrades[data].fullDisplay, layers[layer].upgrades[data])"></span>
          <span v-else>
				<span v-if="tmp[layer].upgrades[data].title">
				  <!--suppress HtmlUnknownTag -->
				  <h3 v-html="tmp[layer].upgrades[data].title"></h3><br>
				</span>
				<span v-html="tmp[layer].upgrades[data].description"></span>
				<span v-if="tmp[layer].upgrades[data].effectDisplay"><br>Currently: <span
                    v-html="run(tmp[layer].upgrades[data].effectDisplay, layers[layer].upgrades[data])"></span></span>
				<span v-if="tmp[layer].upgrades[data].cost"><br><br>Cost:
                  {{ formatWhole(tmp[layer].upgrades[data].cost) }}
                  {{ (tmp[layer].upgrades[data].currencyDisplayName ? tmp[layer].upgrades[data].currencyDisplayName : tmp[layer].resource) }}</span>
			</span>
          </button>
		`
	});

	Vue.component("milestones", {
		props: ["layer"],
		template: `
          <div v-if="tmp[layer].milestones" style="display: flex; justify-content: center;">
          <table style="margin: 10px;">
            <tr v-for="id in Object.keys(tmp[layer].milestones)"
                v-if="tmp[layer].milestones[id]!== undefined && tmp[layer].milestones[id].unlocked && milestoneShown(layer, id)">
              <milestone :layer="layer" :data="id" v-bind:style="tmp[layer].componentStyles.milestone"></milestone>
            </tr>
          </table>
          <br>
          </div>
		`
	});

	Vue.component("milestones-filtered", {
		props: ["layer", "data"],
		template: `
          <div v-if="tmp[layer].milestones" style="display: flex; justify-content: center;">
          <table style="margin: 10px;">
            <tr v-for="id in data"
                v-if="tmp[layer].milestones[id]!== undefined && tmp[layer].milestones[id].unlocked && milestoneShown(layer, id)">
              <milestone :layer="layer" :data="id" v-bind:style="tmp[layer].componentStyles.milestone"></milestone>
            </tr>
          </table>
          <br>
          </div>
		`
	});

	// data = id
	Vue.component("milestone", {
		props: ["layer", "data"],
		template: `
          <td v-if="tmp[layer].milestones && tmp[layer].milestones[data]!== undefined && milestoneShown(layer, data) && tmp[layer].milestones[data].unlocked"
              v-bind:style="[tmp[layer].milestones[data].style]"
              v-bind:class="{milestone: !hasMilestone(layer, data), milestoneDone: hasMilestone(layer, data)}">
          <h3 v-html="tmp[layer].milestones[data].title"></h3><br>
          <b v-html="tmp[layer].milestones[data].requirementDescription"></b><br>
          <span v-html="run(layers[layer].milestones[data].effectDescription, layers[layer].milestones[data])"></span><br>
          <span v-if="(tmp[layer].milestones[data].toggles)&&(hasMilestone(layer, data))"
                v-for="toggle in tmp[layer].milestones[data].toggles"><toggle :layer="layer" :data="toggle"
                                                                              v-bind:style="tmp[layer].componentStyles.toggle"/>&nbsp;</span>
          </td>
		`
	});

	Vue.component("toggle", {
		props: ["layer", "data"],
		template: `
          <button class="smallUpg can" v-bind:style="{'background-color': tmp[data[0]].color}"
                  v-on:click="toggleAuto(data)">{{ player[data[0]][data[1]] ? "ON" : "OFF" }}
          </button>
		`
	});

	// data = function to return the text describing the reset before the amount gained (optional)
	Vue.component("prestige-button", {
		props: ["layer", "data"],
		template: `
          <button v-if="(tmp[layer].type !== 'none')"
                  v-bind:class="{ [layer]: true, reset: true, locked: !tmp[layer].canReset, can: tmp[layer].canReset}"
                  v-bind:style="[tmp[layer].canReset ? {'background-color': tmp[layer].color} : {}, tmp[layer].componentStyles['prestige-button']]"
                  v-html="prestigeButtonText(layer)" v-on:click="doReset(layer)">
          </button>
		`

	});

	// Displays the main resource for the layer
	Vue.component("main-display", {
		props: ["layer", "data"],
		template: `<div class="sticky">
          <div class="upgTable instant">
            <div class="upgRow">
              <bar :layer="layer" :data="'job'"></bar>
              <span style="margin-left: 20px;">Lv. {{ getJobLevel(layer) }}</span>
            </div>
          </div>
          <div class="instant" style="width: 8px; height: 17px;"></div>
          <span v-if="player[layer].points.lt('1e1000')">You have </span>
          <h2 v-bind:style="{'color': tmp[layer].color, 'text-shadow': '0px 0px 10px ' + tmp[layer].color}">
            {{ data ? format(player[layer].points, data) : formatWhole(player[layer].points) }}</h2> {{ tmp[layer].resource }}<span
              v-if="layers[layer].effectDescription">, <span v-html="run(layers[layer].effectDescription, layers[layer])"></span></span>
        </div>
		`
	});

	// Displays the base resource for the layer, as well as the best and total values for the layer's currency, if tracked
	Vue.component("resource-display", {
		props: ["layer"],
		template: `
		<div style="margin-top: -13px">
			<span v-if="tmp[layer].baseAmount"><br>You have {{formatWhole(tmp[layer].baseAmount)}} {{tmp[layer].baseResource}}</span>
			<span v-if="tmp[layer].passiveGeneration"><br>You are gaining {{formatWhole(tmp[layer].resetGain.times(tmp[layer].passiveGeneration))}} {{tmp[layer].resource}} per second</span>
			<br><br>
			<span v-if="tmp[layer].showBest">Your best {{tmp[layer].resource}} is {{formatWhole(player[layer].best)}}<br></span>
			<span v-if="tmp[layer].showTotal">You have made a total of {{formatWhole(player[layer].total)}} {{tmp[layer].resource}}<br></span>
		</div>
		`
	});

	// data = button size, in px
	Vue.component('buyables', {
		props: ['layer', 'data'],
		template: `
		<div v-if="tmp[layer].buyables" class="upgTable">
			<respec-button v-if="tmp[layer].buyables.respec && !(tmp[layer].buyables.showRespec !== undefined && tmp[layer].buyables.showRespec == false)" :layer = "layer" v-bind:style="[{'margin-bottom': '12px'}, tmp[layer].componentStyles['respec-button']]"></respec-button>
			<div v-for="row in tmp[layer].buyables.rows" class="upgRow">
				<div v-for="col in tmp[layer].buyables.cols"><div v-if="tmp[layer].buyables[row*10+col]!== undefined && tmp[layer].buyables[row*10+col].unlocked" class="upgAlign" v-bind:style="{'margin': '7px', 'height': (data ? data : 'inherit'),}">
					<buyable :layer = "layer" :data = "row*10+col" :size = "data"></buyable>
				</div></div>
				<br>
			</div>
		</div>
	`
	})

	// data = id of buyable
	Vue.component('buyable', {
		props: ['layer', 'data', 'size'],
		template: `
		<div v-if="tmp[layer].buyables && tmp[layer].buyables[data]!== undefined && tmp[layer].buyables[data].unlocked" style="display: grid">
			<button v-bind:class="{ buyable: true, can: tmp[layer].buyables[data].canBuy, locked: !tmp[layer].buyables[data].canAfford, bought: player[layer].buyables[data].gte(tmp[layer].buyables[data].purchaseLimit)}"
			v-bind:style="[tmp[layer].buyables[data].canBuy ? {'background-color': tmp[layer].buyables[data].color || tmp[layer].color} : {}, size ? {'height': size, 'width': size} : {}, tmp[layer].componentStyles.buyable, tmp[layer].buyables[data].style]"
			v-on:click="buyBuyable(layer, data)" @mousedown="start" @mouseleave="stop" @mouseup="stop" @touchstart="start" @touchend="stop" @touchcancel="stop">
				<span v-if= "tmp[layer].buyables[data].title"><h2 v-html="tmp[layer].buyables[data].title"></h2><br></span>
				<span v-bind:style="{'white-space': 'pre-line'}" v-html="run(layers[layer].buyables[data].display, layers[layer].buyables[data])"></span>
				<node-mark :layer='layer' :data='tmp[layer].buyables[data].marked'></node-mark>

			</button>
			<br v-if="(tmp[layer].buyables[data].sellOne !== undefined && !(tmp[layer].buyables[data].canSellOne !== undefined && tmp[layer].buyables[data].canSellOne == false)) || (tmp[layer].buyables[data].sellAll && !(tmp[layer].buyables[data].canSellAll !== undefined && tmp[layer].buyables[data].canSellAll == false))">
			<sell-one :layer="layer" :data="data" v-bind:style="tmp[layer].componentStyles['sell-one']" v-if="(tmp[layer].buyables[data].sellOne)&& !(tmp[layer].buyables[data].canSellOne !== undefined && tmp[layer].buyables[data].canSellOne == false)"></sell-one>
			<sell-all :layer="layer" :data="data" v-bind:style="tmp[layer].componentStyles['sell-all']" v-if="(tmp[layer].buyables[data].sellAll)&& !(tmp[layer].buyables[data].canSellAll !== undefined && tmp[layer].buyables[data].canSellAll == false)"></sell-all>
		</div>
		`,
		data() { return { interval: false, time: 0,}},
		methods: {
			start() {
				if (!this.interval) {
					this.interval = setInterval((function() {
						if(this.time >= 5)
							buyBuyable(this.layer, this.data)
						this.time = this.time+1
					}).bind(this), 50)}
			},
			stop() {
				clearInterval(this.interval)
				this.interval = false
			  	this.time = 0
			}
		},
	})

	Vue.component("respec-button", {
		props: ["layer", "data"],
		template: `
			<div>
				<div class="tooltipBox"><input type="checkbox" v-model="player[layer].noRespecConfirm" ><tooltip v-bind:text="'Disable respec confirmation'"></tooltip></div>
				<button v-if="tmp[layer].buyables && tmp[layer].buyables.respec && !(tmp[layer].buyables.showRespec !== undefined && tmp[layer].buyables.showRespec == false)" v-on:click="respecBuyables(layer)" v-bind:class="{ longUpg: true, can: player[layer].unlocked, locked: !player[layer].unlocked }" style="margin-right: 18px">{{tmp[layer].buyables.respecText ? tmp[layer].buyables.respecText : "Respec"}}</button>
			</div>
			`
	})

	// data = button size, in px
	Vue.component("clickables", {
		props: ["layer", "data"],
		template: `
          <div v-if="tmp[layer].clickables" class="upgTable">
          <master-button
              v-if="tmp[layer].clickables.masterButtonPress && !(tmp[layer].clickables.showMasterButton !== undefined && tmp[layer].clickables.showMasterButton === false)"
              :layer="layer"
              v-bind:style="[{'margin-bottom': '12px'}, tmp[layer].componentStyles['master-button']]"></master-button>
          <div v-for="row in tmp[layer].clickables.rows" class="upgRow">
            <div v-for="col in tmp[layer].clickables.cols">
              <div v-if="tmp[layer].clickables[row*10+col]!== undefined && tmp[layer].clickables[row*10+col].unlocked"
                   class="upgAlign"
                   v-bind:style="{'margin': '7px', 'height': (data ? data : 'inherit'),}">
                <clickable :layer="layer" :data="row*10+col" :size="data"
                           v-bind:style="tmp[layer].componentStyles.clickable"></clickable>
              </div>
            </div>
            <br>
          </div>
          </div>
		`
	});

	// data = id of clickable
	Vue.component("clickable", {
		props: ["layer", "data", "size"],
		template: `
        <button
              v-if="tmp[layer].clickables && tmp[layer].clickables[data]!== undefined && tmp[layer].clickables[data].unlocked !== false"
              v-bind:class="{ upg: true, can: tmp[layer].clickables[data].canClick !== false, locked: tmp[layer].clickables[data].canClick === false, ...tmp[layer].clickables[data].class}"
              v-bind:style="[tmp[layer].clickables[data].canClick !== false ? {'background-color': tmp[layer].clickables[data].color || tmp[layer].color} : { 'background-color': tmp[layer].clickables[data].style?.backgroundColor }, size ? {'height': size, 'width': size} : {}, tmp[layer].clickables[data].style]"
              v-on="handlers">
          <span v-if="tmp[layer].clickables[data].title">
			  		<!--suppress HtmlUnknownTag -->
			  		<h2 v-html="tmp[layer].clickables[data].title"></h2><br>
					</span>
          <span v-bind:style="{'white-space': 'pre-line'}" v-html="run(layers[layer].clickables[data].display, layers[layer].clickables[data])"></span>
          <node-mark :layer='layer' :data='tmp[layer].clickables[data].marked'></node-mark>
		</button>
		`,
		data() {
			const {layer, data} = this;
			const handlers = {
				click: () => clickClickable(layer, data),
				mouseenter: layers[layer].clickables[data].touchstart,
				touchstart: layers[layer].clickables[data].touchstart,
				touchend: layers[layer].clickables[data].touchend,
				mouseleave: layers[layer].clickables[data].touchend
			};
			for (let cb in handlers) {
				if (handlers[cb] == null) {
					delete handlers[cb];
				}
			}
			return {handlers};
		}
	});

	Vue.component("master-button", {
		props: ["layer", "data"],
		template: `
          <button
              v-if="tmp[layer].clickables && tmp[layer].clickables.masterButtonPress && !(tmp[layer].clickables.showMasterButton !== undefined && tmp[layer].clickables.showMasterButton === false)"
              v-on:click="run(tmp[layer].clickables.masterButtonPress, tmp[layer].clickables)"
              v-bind:class="{ longUpg: true, can: player[layer].unlocked, locked: !player[layer].unlocked }">{{ tmp[layer].clickables.masterButtonText ? tmp[layer].clickables.masterButtonText : "Click me!" }}
          </button>
		`
	});


	// data = button size, in px
	Vue.component('grid', {
		props: ['layer', 'data'],
		template: `
		<div v-if="tmp[layer].grid" class="upgTable">
			<div v-for="row in tmp[layer].grid.rows" class="upgRow">
				<div v-for="col in tmp[layer].grid.cols"><div v-if="run(layers[layer].grid.getUnlocked, layers[layer].grid, row*100+col)"
					class="upgAlign" v-bind:style="{'margin': '1px',  'height': 'inherit',}">
					<gridable :layer = "layer" :data = "row*100+col" v-bind:style="tmp[layer].componentStyles.gridable"></gridable>
				</div></div>
				<br>
			</div>
		</div>
	`
	})

	Vue.component('gridable', {
		props: ['layer', 'data'],
		template: `
		<button
		v-if="tmp[layer].grid && player[layer].grid[data]!== undefined && run(layers[layer].grid.getUnlocked, layers[layer].grid, data)"
		v-bind:class="{ tile: true, can: canClick, locked: !canClick}"
		v-bind:style="[canClick ? {'background-color': tmp[layer].color} : {}, gridRun(layer, 'getStyle', player[this.layer].grid[this.data], this.data)]"
		v-on:click="clickGrid(layer, data)"  @mousedown="start" @mouseleave="stop" @mouseup="stop" @touchstart="start" @touchend="stop" @touchcancel="stop">
			<span v-if= "layers[layer].grid.getTitle"><h3 v-html="gridRun(this.layer, 'getTitle', player[this.layer].grid[this.data], this.data)"></h3><br></span>
			<span v-bind:style="{'white-space': 'pre-line'}" v-html="gridRun(this.layer, 'getDisplay', player[this.layer].grid[this.data], this.data)"></span>
		</button>
		`,
		data() { return { interval: false, time: 0,}},
		computed: {
			canClick() {
				return gridRun(this.layer, 'getCanClick', player[this.layer].grid[this.data], this.data)}
		},
		methods: {
			start() {
				if (!this.interval && layers[this.layer].grid.onHold) {
					this.interval = setInterval((function() {
						if(this.time >= 5 && gridRun(this.layer, 'getCanClick', player[this.layer].grid[this.data], this.data)) {
							gridRun(this.layer, 'onHold', player[this.layer].grid[this.data], this.data)						}
						this.time = this.time+1
					}).bind(this), 50)}
			},
			stop() {
				clearInterval(this.interval)
				this.interval = false
			  	this.time = 0
			}
		},
	})

	// data = button size, in px
	Vue.component("microtabs", {
		props: ["layer", "data"],
		computed: {
			currentTab() {
				return player.subtabs[layer][data];
			}
		},
		template: `
          <div v-if="tmp[layer].microtabs" :style="{'border-style': 'solid'}">
          <div class="upgTable instant">
            <tab-buttons :layer="layer" :data="tmp[layer].microtabs[data]" :name="data"
                         v-bind:style="tmp[layer].componentStyles['tab-buttons']"></tab-buttons>
          </div>
          <layer-tab v-if="tmp[layer].microtabs[data][currentTab].embedLayer"
                     :layer="tmp[layer].microtabs[data][currentTab].embedLayer" :embedded="true"></layer-tab>

          <column v-else v-bind:style="tmp[layer].microtabs[data][currentTab].style" :layer="layer"
                  :data="tmp[layer].microtabs[data][currentTab].content"></column>
          </div>
		`
	});


	// data = id of the bar
	Vue.component("bar", {
		props: ["layer", "data"],
		computed: {
			style() {return constructBarStyle(this.layer, this.data)}
		},
		template: `
          <div v-if="tmp[layer].bars && tmp[layer].bars[data].unlocked !== false"
               v-bind:style="{'position': 'relative'}">
          <div
              v-bind:style="[tmp[layer].bars[data].style, style.dims, {'display': 'table', 'borderRadius': '10px', 'boxShadow': '0 0 10px 2px var(--shadowColor), inset 0 0 10px 4px var(--innerShadowColor)'}]">
            <div class="overlayTextContainer barBorder"
                 v-bind:style="[tmp[layer].bars[data].borderStyle, style.dims]">
              <span class="overlayText" v-bind:style="[tmp[layer].bars[data].style, tmp[layer].bars[data].textStyle]"
                    v-html="run(layers[layer].bars[data].display, layers[layer].bars[data])"></span>
            </div>
            <div class="barBG barBorder"
                 v-bind:style="[tmp[layer].bars[data].style, tmp[layer].bars[data].baseStyle, tmp[layer].bars[data].borderStyle, style.dims]">
              <div class="fill"
                   v-bind:style="[tmp[layer].bars[data].style, tmp[layer].bars[data].fillStyle, style.fillDims]"></div>
            </div>
          </div>
          </div>
		`
	});


	Vue.component("achievements", {
		props: ["layer"],
		template: `
          <div v-if="tmp[layer].achievements" class="upgTable">
          <div v-for="row in tmp[layer].achievements.rows" class="upgRow">
            <div v-for="col in tmp[layer].achievements.cols">
              <div
                  v-if="tmp[layer].achievements[row*10+col]!== undefined && tmp[layer].achievements[row*10+col].unlocked"
                  class="upgAlign">
                <achievement :layer="layer" :data="row*10+col"
                             v-bind:style="tmp[layer].componentStyles.achievement"></achievement>
              </div>
            </div>
          </div>
          <br>
          </div>
		`
	});

	// data = id
	Vue.component("achievement", {
		props: ["layer", "data"],
		template: `
		<div v-if="tmp[layer].achievements && tmp[layer].achievements[data]!== undefined && tmp[layer].achievements[data].unlocked" v-bind:class="{ [layer]: true, achievement: true, tooltipBox:true, locked: !hasAchievement(layer, data), bought: hasAchievement(layer, data)}"
			v-bind:style="achievementStyle(layer, data)">
			<tooltip :text="
			(tmp[layer].achievements[data].tooltip == '') ? false : hasAchievement(layer, data) ? (tmp[layer].achievements[data].doneTooltip ? tmp[layer].achievements[data].doneTooltip : (tmp[layer].achievements[data].tooltip ? tmp[layer].achievements[data].tooltip : 'You did it!'))
			: (tmp[layer].achievements[data].goalTooltip ? tmp[layer].achievements[data].goalTooltip : (tmp[layer].achievements[data].tooltip ? tmp[layer].achievements[data].tooltip : 'LOCKED'))
		"></tooltip>
			<span v-if= "tmp[layer].achievements[data].name"><br><h3 v-bind:style="tmp[layer].achievements[data].textStyle" v-html="tmp[layer].achievements[data].name"></h3><br></span>
		</div>
		`
	});

	// Data is an array with the structure of the tree
	Vue.component("tree", {
		props: ["layer", "data"],
		computed: {
			key() {
				return this.$vnode.key;
			}
		},
		template: `
          <div>
          <span class="upgRow" v-for="(row, r) in data">
				<!--suppress HtmlUnknownTag -->
				<table>
					<span v-for="(node, id) in row" style="{width: 0}">
						<tree-node :layer='node' :abb='tmp[node].symbol' :key="key + '-' + r + '-' + id"></tree-node>
					</span>
					<tr>
					  <!--suppress HtmlUnknownTag -->
					  <table><button class="treeNode hidden"></button></table>
					</tr>
				</table>
			</span>
          </div>
		`
	});

	// Updates the value in player[layer][data]
	Vue.component('text-input', {
		props: ['layer', 'data'],
		template: `
			<input class="instant" :id="'input-' + layer + '-' + data" :value="player[layer][data].toString()" v-on:focus="focused(true)" v-on:blur="focused(false)"
			v-on:change="player[layer][data] = toValue(document.getElementById('input-' + layer + '-' + data).value, player[layer][data])">
		`
	})

// Updates the value in player[layer][data]
	Vue.component('slider', {
		props: ['layer', 'data'],
		template: `
			<div class="tooltipBox">
			<tooltip :text="player[layer][data[0]]"></tooltip><input type="range" v-model="player[layer][data[0]]" :min="data[1]" :max="data[2]"></div>
		`
	})

	// These are for buyables, data is the id of the corresponding buyable
	Vue.component("sell-one", {
		props: ["layer", "data"],
		template: `
          <button
              v-if="tmp[layer].buyables && tmp[layer].buyables[data].sellOne && !(tmp[layer].buyables[data].canSellOne !== undefined && tmp[layer].buyables[data].canSellOne === false)"
              v-on:click="run(tmp[layer].buyables[data].sellOne, tmp[layer].buyables[data])"
              v-bind:class="{ longUpg: true, can: player[layer].unlocked, locked: !player[layer].unlocked }">{{ tmp[layer].buyables.sellOneText ? tmp[layer].buyables.sellOneText : "Sell One" }}
          </button>
		`
	});
	Vue.component("sell-all", {
		props: ["layer", "data"],
		template: `
          <button
              v-if="tmp[layer].buyables && tmp[layer].buyables[data].sellAll && !(tmp[layer].buyables[data].canSellAll !== undefined && tmp[layer].buyables[data].canSellAll === false)"
              v-on:click="run(tmp[layer].buyables[data].sellAll, tmp[layer].buyables[data])"
              v-bind:class="{ longUpg: true, can: player[layer].unlocked, locked: !player[layer].unlocked }">{{ tmp[layer].buyables.sellAllText ? tmp[layer].buyables.sellAllText : "Sell All" }}
          </button>
		`
	});

	// SYSTEM COMPONENTS
	Vue.component('node-mark', systemComponents['node-mark'])
	Vue.component('tab-buttons', systemComponents['tab-buttons'])
	Vue.component('tree-node', systemComponents['tree-node'])
	Vue.component('layer-tab', systemComponents['layer-tab'])
	Vue.component('overlay-head', systemComponents['overlay-head'])
	Vue.component('info-tab', systemComponents['info-tab'])
	Vue.component('options-tab', systemComponents['options-tab'])
	Vue.component('tooltip', systemComponents['tooltip'])
	Vue.component('particle', systemComponents['particle'])


	Vue.component("sticky", {
		props: ["layer", "data"],
		template: `
          <div class="sticky" v-bind:style="{ top: data[0] || 0 }">
          <div v-bind:is="data[1][0]" :layer="layer" :data="data[1][1]"
               v-bind:style="tmp[layer].componentStyles[data[1][0]]"></div>
          </div>
		`
	});

	Vue.component("PerfectScrollbar", Vue2PerfectScrollbar.PerfectScrollbar);

	app = new Vue({
		el: "#app",
		data: {
			player,
			tmp,
			Decimal,
			format,
			formatWhole,
			formatTime,
			formatSmall,
			focused,
			getThemeName,
			layerunlocked,
			doReset,
			buyUpg,
			startChallenge,
			milestoneShown,
			keepGoing,
			hasUpgrade,
			hasMilestone,
			hasAchievement,
			hasChallenge,
			maxedChallenge,
			inChallenge,
			canAffordUpgrade,
			canBuyBuyable,
			canCompleteChallenge,
			subtabShouldNotify,
			subtabResetNotify,
			challengeStyle,
			challengeButtonText,
			constructBarStyle,
			constructParticleStyle,
			VERSION,
			LAYERS,
			hotkeys,
			activePopups,
			particles,
			mouseX,
			mouseY,
			shiftDown,
			ctrlDown,
			lastTenTicks
		},
	});
}