// plugin/vue-renderer/renderer/render-page-app.js
// idea taken from: https://lachlan-miller.me/articles/vue-3-pdf-customer-renderer
// see: render-page-new.js

import './render-init.js' // inits globals like console.warn = print
import { provide, defineComponent, compile, createRenderer } from '../vuelib.js' // 'vue', vue is using: 'vue/dist/vue.esm-bundler.js'
import { newDocument } from './element.js'
import { createNodeOps } from './nodeOps.js'

const App = defineComponent({
	name: 'NcRenderApp' /* ,
	setup() {
		provide('state', state)
		return { rec: state.rec, hdr: state.hdr } // ...toRefs(state) if state is reactive
	},
	render: compile(`${html}`) */
})

function createApp(componentArr, ...args) {
	const nodeMap = []
	const nodeOps = createNodeOps(nodeMap) // createNodeOps generates nodeMap
	const renderer = createRenderer(nodeOps)
	const app = renderer.createApp(...args) // vue call
	for (let key in componentArr) {
		app.component(key, componentArr[key])
	}
	const { mount } = app
	app.mount = doc => {
		const proxy = mount(doc)
		doc.nodeMap = nodeMap
		return proxy
	}
	return app
}

const replaceVShow = new RegExp('v-show=', 'g')
export function renderPageApp(componentArr, arg) {
	let param
	if (typeof arg === 'string') {
		param = JSON.parse(arg)
	} else {
		param = arg
	}
	const state = param.state || {}
	// state.rec = param.state.rec
	// state.hdr = param.state.hdr
	// console.log('html', html)
	// console.log('stateRec', stateRec)
	// const state = newState('nc-render', stateRec)
	if (!state.rec) {
		state.rec = {}
	}
	state.rec.printing = true

	// return Object.assign({ style: appStyle }, toRefs(state)) // this is old-browser compatible version of '...state'
	// return { ...state, state } // ...toRefs(state) if state is reactive
	// components: componentArr, // create later by app.component(), components must be in app, here is not enough
	// Modelled after https://github.com/vuejs/vue-next/blob/master/packages/runtime-dom/src/index.ts#L61
	App.setup = () => {
		provide('state', state)
		return state // { rec: state.rec, hdr: state.hdr, arr: state.arr, grid: state.grid, data: state.data } // ...toRefs(state) if state is reactive
	}
	if (param.html) {
		const html = param.html.replace(replaceVShow, 'v-if=')
		App.render = compile(`${html}`)
	}
	const doc = newDocument()
	const app = createApp(componentArr, App)
	app.mount(doc) // this creates doc.nodeMap
	// app.unmount() // not needed, let gc handle it
	doc.nodeMap.shift() // The shift() method removes the first item of an array, we don't need first root
	if (doc.nodeMap.length > 0) {
		delete doc.nodeMap[0].parent
	}

	const nodeMap = doc.nodeMap.map(item => {
		const ret = {}
		for (const key in item) {
			if (!key.startsWith('_') && key !== 'nodeMap') {
				ret[key] = item[key]
			}
		}
		if (item.__vnode && item.__vnode.props) {
			const item2 = item.__vnode.props
			ret.props = {}
			for (const key2 in item2) {
				if (item2[key2] != null && typeof item2[key2] !== 'function') {
					ret.props[key2] = item2[key2]
				}
			}
		}
		return ret
	})
	return JSON.stringify(nodeMap, null, 2)
}
