<template>
	<div
		v-if="openMessageBox"
		class="fixed inset-0 bg-gray-600 overflow-y-auto h-full w-full z-80 dark:bg-gray-900 opacity-97"
	>
	<message-box-view
		:messageType="message_type"
		:openMessageBox="openMessageBox"
		:show_input="show_input"
		:input_placeholder="input_placeholder"
		:input_btns="input_btns"
		:select_ops="select_ops"
		:data_url_encoded="data_url_encoded"
		:inpType="oneInputType"
		@onInput="onInput"
		@onMessageBox="onMessageBox"
		@onLoadModel="onLoadModel"
	/>
	</div>
	<div v-if="show_content && usersData" class="font-sans antialiased">
		<div class="container mx-auto max-w-screen-2xl main-container">
			<nav-menu
			  class="bg-light-300 dark:bg-gray-900"
				:position="NavPosition.header"
				:openMessageBox="openMessageBox"
				:fixMenu="fixMenu"
				:show_infopanel="show_infopanel"
				:dataAuth="false"
				:useInfoPanel="false"
				:useLogin="true"
				:showinfo="show_info"
				:authinfo="auth_info"
				:needSave="needSave"
				:useEdit="true"
				:prefix="prefix"
				@onNavMenu="onNavMenu"
			/>
			<main
				:id="`${prefix}-wrapper`"
				class="rounded flex flex-col sm:flex-row-reverse shadow-2xl"
				:class="{ 'mt-11': fixMenu }"
			>
				<div
					v-if="show_infopanel"
					id="sidebar"
					class="rounded-r w-full lg:w-60 sm:max-w-sm p-8 border-l-1 border-indigo-200 bg-gradient-to-b from-indigo-300 via-indigo-200 to-indigo-100 dark:bg-gray-600 dark:from-indigo-700 dark:via-indigo-600 dark:to-indigo-800"
				>
				</div>
				<div class="content w-full p-5">
						<div v-for="(sec,idx) in dataSections" :key="idx" class="flex justify-center border-gray-300 dark:border-gray-500 border-b-1 py-2 my-1">
							<div :id="`${prefix}-${sec}`" class="mb-3 w-full">
								<h2 class="section-headline noprint" >
									<span v-if="show_data[sec]"> {{t(`users.${sec.replace('sec_','')}`,sec)}} </span>
									<button
											v-if="show_data[sec]"
											class="no-print text-sm float-right icon-btn mt-2 ml-2 !outline-none text-gray-500 dark:text-gray-400"
											@click="onHelp(sec)" 
										>
											<div i-carbon-help/>
									</button>
									<button
										class="no-print text-sm float-right icon-btn mt-2 !outline-none text-gray-500 dark:text-gray-400"
										@click.prevent="onDataView(sec)"
									>
										<div v-if="show_data[sec]" i-carbon-view-off />
										<div v-else class="noprint flex">
											<div class="-mt-0.5 mr-2 line-through">{{t(`menu.${sec}`,sec)}}</div>
											<div i-carbon-view />
										</div>
									</button>
									<button
										v-if="show_data[sec]"
										class="no-print text-sm float-right icon-btn mt-2 !outline-none text-gray-500 dark:text-gray-400 mr-2"
										@click="onSaveUser(sec)"
									>
										<div i-carbon-checkmark-outline/>
									</button>
								</h2>
								<div v-if="varsUser[sec] && show_data[sec]" v-for="(item) in Object.keys(varsUser[sec])">
										<label 
										  :for="`input-${sec}-${item}`" class="form-label inline-block mb-2 text-gray-700 dark:text-gray-500">
											{{t(`menu.${sec}`,item)}}
										</label>
											<div v-if="varsUser[sec][item].vars">
												<DataInput
													:dataVars="varsUser[sec][item].vars"
													:section="sec"
													:typ="varsUser[sec][item].typ"
													:dataValue="getDataFromItem(item) as Object"
													:varname="item"
												  :vardef="varsUser[sec][item]"
													:title="`${sec}`"
													:labelitms="varsUser[sec][item].labelitms? varsUser[sec][item].labelitms : ''"
													:edititem="edititems"
													:showitem="show_data[sec]"
													:validate="varsUser[sec][item].valid ? varsUser[sec][item].valid : ''"
													:messages="true"
													@input-change="onInputChange"
												/>	
												<div v-if="varsUser[sec][item].from">
													<button
														v-if="show_data[sec]"
														class="flex no-print text-sm float-right icon-btn mt-2 ml-2 !outline-none text-gray-500 dark:text-gray-400"
														@click="onViewInput(sec)" 
													>
														<div class="mr-2 mb-2">{{t(`menu.${sec}`,sec)}}</div>
														<carbon-edit />
													</button>
													<InputValue 
														v-if="varsUser[sec][item].from && show_inputText[sec]"
														:section="sec"
														:typ="varsUser[sec][item].from.typ"
														:dataValue="usersData[item] as string"
														:varname="item"
														:vardef="varsUser[sec][item]"
												    :title="`${prefix}.${item}`"
														:rows="varsUser[sec][item].from.rows"
														:labelitms="varsUser[sec][item].from.labelitms? varsUser[sec][item].from.labelitms : ''"
														:edititem="edititems"
														:showitem="show_data[sec]"
														:validate="varsUser[sec][item].from.valid ? varsUser[sec][item].from.valid : ''"
														:messages="true"
														@input-change="onInputValueChange"
														/>	
												</div>
											</div>
											<div v-if=" varsUser[sec][item].typ !== InputValueOption.object">
												<InputValue 
												:section="sec"
												:typ="varsUser[sec][item].typ"
												:dataValue="getDataFromItem(item) as string"
												:varname="item"
												:vardef="varsUser[sec][item]"
												:title="`${prefix}.${item}`"
												:rows="varsUser[sec][item].rows"
												:labelitms="varsUser[sec][item].labelitms? varsUser[sec][item].labelitms : ''"
												:edititem="edititems"
												:showitem="show_data[sec]"
												:validate="varsUser[sec][item].valid ? varsUser[sec][item].valid : ''"
												:messages="true"
												@input-change="onInputChange"
												/>	
											</div>
											<div v-if="show_help[sec]" class="my-2 text-gray-600 dark:text-gray-500" :class="{'mt-8 border-gray-200 dark:border-gray-600 border-t-1 pt-2': !show_inputText[sec]}">
												<span v-html="t(`users.msg_${sec.replace('sec_','')}`,'').replaceAll('passwdEnc',useState().PASSWD_ENC.value)" />
											</div>
								</div>
							</div>
						</div>
				</div>
			</main>
			<div
   	    v-if="show_content" 
				class="mr-auto w-full lg:w-1/2 text-center text-sm mx-2 text-gray-600 border-gray-300 border-1 border-b-0 rounded-t-xl"
			>
				<nav-menu
				  class="shadow-xl bg-light-300 dark:bg-gray-900"
					:position="NavPosition.footer"
					:fixMenu="fixMenu"
					:show_infopanel="show_infopanel"
				  :dataAuth="false"
				  :useInfoPanel="false"
				  :useLogin="true"
					:showinfo="show_info"
					:authinfo="auth_info"
					:needSave="needSave"
				  :useEdit="true"
					prefix="sec"
				  :openMessageBox="openMessageBox"
					@onNavMenu="onNavMenu"
				/>
			</div>
		</div>
	</div>
<div v-else class="text-center m-auto">
	<img v-if="isDark"
		class="m-auto mt-5"
		width="250"
		:src="`${assetsPath}/images/genadmin_b.svg`"
	/>
	<img v-else
		class="m-auto mt-5"
		width="250"
		:src="`${assetsPath}/images/genadmin_w.svg`"
	/>
	<h2 class="mt-8 text-2xl text-gray-700 dark:text-gray-400">{{ t('message.loading', 'Loading') }}...</h2>
	<h4>{{useState().connection.value.state}}</h4>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const i18n = useI18n()
const { t } = useI18n()
const router = useRouter()

import YAML from 'yaml'
import DataInput from '@/forms/DataInput.vue'
import InputValue from '@/InputValue.vue'
import MessageBoxView from '~/components/MessageBoxView.vue'
import NavMenu from '@/NavMenu.vue'
import { isDark} from '~/composables'
import useState from '~/hooks/useState'
import { parseJwt,checkUserAuth } from '~/hooks/utilsAuth'
import { load_data_model,load_currentRoute} from '~/hooks/loads'
import { fetch_json } from '~/hooks/utils'
import { track_action } from '~/hooks/tracking'
import { MessageType } from '~/typs'
import { UsersDataType, UsersDataViewType, UsersInvitationsType } from '~/typs/users'
import { MessageBoxType, NavPosition, InputBtnsType, ShowInfoType, ModelType } from '~/typs/cv'
import { InputValueOption } from '~/typs/inputs'
import { UsersAccountsType, ModelsUsersType } from '~/typs/users'
import { show_message,send_data } from '~/hooks/utils'
import { b64_to_utf8,utf8_to_b64 } from '~/hooks/tools'

const dataSections = useState().dataSections
const dataKeys = ['usersData','modelsData','invitations','authzModel','authzPolicy']
const usersData= ref({} as UsersDataType)
const varsUser = useState().varsUser

const show_data = ref({} as UsersDataViewType)
const show_help = ref({} as UsersDataViewType)

const usersAccounts = ref({} as UsersAccountsType)
const modelsUsers = ref({} as ModelsUsersType)
const invitations = ref({} as UsersInvitationsType)

const prefix = 'users'
const edititems = ref(false)
const show_inputText = ref({} as UsersDataViewType)

const assetsPath = useState().ASSETS_PATH
const routeKy = router.currentRoute.value.params.ky || router.currentRoute.value.query.k || ''
const message_type = ref(MessageBoxType.NotSet)
const fixMenu = ref(false)
const show_content = ref(true)
const show_infopanel = ref(false)
const openMessageBox = ref(false)
const needSave = ref(false)
const show_input = ref(false)
const data_url_encoded = ref('')
const input_btns = ref([] as InputBtnsType[])
const input_placeholder = ref('')
const oneInputType = ref('')

const onInputChange = (data: {sec: string, key: string, idx:number,  val: any}) => {
	if (data.key && data.val) {
		switch (data.key) {
			case 'usersData':
		    usersAccounts.value = data.val
			  usersData.value.usersData = YAML.stringify(data.val) 
				break
			case 'modelsData':
		    modelsUsers.value= data.val
			  usersData.value.modelsData = YAML.stringify(data.val) 
				break
			case 'invitations':
		    invitations.value= data.val
			  usersData.value.invitations = YAML.stringify(data.val) 
				break
			case 'authzModel':
			  usersData.value.authzModel = data.val
				break
			case 'authzPolicy':
			  usersData.value.authzPolicy = data.val
				break
		}	
	}
}
const onInputValueChange = (data: {sec: string, key: string, idx:number,  val: string}) => {
	if (data.key && data.val && data.val.length ) {
		switch (data.key) {
			case 'usersData':
			  usersData.value.usersData = data.val 
		    usersAccounts.value = YAML.parse(data.val)
				break
			case 'modelsData':
			  usersData.value.modelsData = data.val 
		    modelsUsers.value = YAML.parse(data.val)
				break
			case 'invitations':
			  usersData.value.invitations = data.val 
		    invitations.value = YAML.parse(data.val)
				break
			case 'authzModel':
			  usersData.value.authzModel = data.val
				break
			case 'authzPolicy':
			  usersData.value.authzPolicy = data.val
				break
		}	
	}
}
const onInput = (btn: InputBtnsType) => {
	switch (btn.id) {
		case 'ok':
			break
		case 'cancel':
			break
	}
	show_input.value = false
}
const getDataFromItem= (item: string):any => {
	switch (item) {
		case 'usersData':
		 return usersAccounts.value
		case 'modelsData':
		 return modelsUsers.value
		case 'invitations':
		 return invitations.value
		case 'authzModel':
		 return usersData.value.authzModel 
		case 'authzPolicy':
		 return usersData.value.authzPolicy 
		default:
		 return {}
	}
}
const select_ops = ref({} as ModelType)
const show_info = ref({} as ShowInfoType)
const auth_info = useState().authinfo
const useEdit = ref(true)
const refresh = () => {
	show_content.value = false
	setTimeout(() => show_content.value = true, 1)
}
const onCloseBtn = () => {
	edititems.value = false
	needSave.value = false
}
const onEditBtn = () => {
	edititems.value = true
	needSave.value = true
	auth_info.value.editable = true
	useEdit.value = true
}
const onNavMenu = (item: { src: string, target: string }) => {
	switch (item.src) {
		case 'editable':
			if (edititems.value) {
			  onCloseBtn()
			} else {
			  onEditBtn()
			}
			break
		case 'locale':
	    track_action(null, { ref: 'locale',text: i18n.locale.value}, 'locale')
			refresh()
			break
		case 'infopanel':
	    track_action(null, { ref: 'onNavMenu',text: 'item.src'})
			show_infopanel.value = !show_infopanel.value
			break
		case 'fixmenu':
	    track_action(null, { ref: 'onNavMenu',text: 'item.src'})
			fixMenu.value = !fixMenu.value
			break
		case 'endinput':
			show_input.value = false
			break
		case 'select':
	    track_action(null, { ref: 'onNavMenu',text: 'item.src'})
			message_type.value = MessageBoxType.Select
			openMessageBox.value = true
			break
		case 'save':
	    track_action(null, { ref: 'onNavMenu',text: 'item.src'})
			input_placeholder.value = `${t('name', 'Name')} o 'config'`
			show_input.value = true
			message_type.value = MessageBoxType.Save
			data_url_encoded.value = ''
			openMessageBox.value = true
			break
		case 'editable':
	    track_action(null, { ref: 'onNavMenu',text: 'item.src'})
			useState().authinfo.value.editable = !useState().authinfo.value.editable
			const state = useState().authinfo.value.editable ? 'on' : 'off'
			const msgTyp = state === 'on' ? MessageType.Warning :  MessageType.Info
      show_message(msgTyp, `${t('saveload.editMode','Edit Mode')} ${t('cv.'+state,'')}`)
			break
		case 'viewchange':
	    track_action(null, { ref: 'onNavMenu',text: 'item.src'})
			useState().authinfo.value.viewchange = !useState().authinfo.value.viewchange
			break
		case 'goto':
			if (item.target) {
				const dom_id = document.getElementById(item.target)
				if (dom_id) {
					track_action(null, { ref: 'gotp',text: item.target}, 'goto')
					dom_id.scrollIntoView({ behavior: 'smooth', block: 'start', inline: 'nearest' })
					setTimeout(() => window.scrollBy(0, -40), 4000)
				}
			}
			break
	}
}
const saveData = async(mode: string,val: string, newData?: UsersDataType ) => {
	const url = useState().CONFURLS.value.sendusers || ''
  message_type.value = MessageBoxType.Save
	const payload = parseJwt(localStorage.getItem(useState().AUTHKEY.value))
	const postdata: any = {
		id:  payload.id ? payload.id : '',
		val: val.length > 0 ? val : 'usersData',
		data: newData ? newData : {...usersData.value},
	} 
	Object.keys(postdata.data).forEach(ky => {
	 	if (postdata.data[ky]) {
			postdata.data[ky]= utf8_to_b64(postdata.data[ky])
	 	}
	})
	if (mode == 'send' && url.length > 0) {
		onMessageBox({src: 'done', val: ''})
		const [res,err] = await send_data(url, postdata, true, true)
		if (err && err.length > 0 ) {
			show_message(MessageType.Error, `Error: ${err}`,2000)
		} else if (res && res.status && res.status === 'ok') {
	    track_action(null, { ref: 'saveData',text: `${url} -> ${val}`})
		  show_message(MessageType.Success, `${t('saveload.dataSaved','Data saved')}`,2000,() => { 
				edititems.value = false
				needSave.value = false
		  })
		}
	} else {
	  track_action(null, { ref: 'saveData',text: `local_json -> ${val}`})
		show_message(MessageType.Warning, `${t('saveload.saveLocalFile','Save Data tLocal File')}`,2000,() => { 
		  data_url_encoded.value = `text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(postdata))}`
		})
	}
}
const onMessageBox = (item: { src: string, val: string }) => {
	switch (item.src) {
		case 'savedata':
			show_input.value = false
			saveData('local', item.val)
			break
		case 'sendata':
			show_input.value = false
			saveData('send', item.val)
			break
		case 'oneinput':
			const r = async() => {
				if (await checkUserAuth(item.val)) {
					oneInputType.value='text'
			    openMessageBox.value = false
				  if (!await load_currentRoute(router.currentRoute.value)) {
					   show_message(MessageType.Error, `${t('saveload.loaderror','Load error')}`,2000)
					}
				} else {
					show_message(MessageType.Error, `${t('saveload.autherror','Auth error')}`,2000)
				}
			}
			r()
		  break
		case 'endinput':
			show_input.value = false
			break
		case 'done':
			openMessageBox.value = false
			break
		case 'open':
			openMessageBox.value = true
			break
	}
}
const onLoadModel = (model: { id: string}) => {
	const url = useState().CONFURLS.value.data || ''
	if ( url.length > 0) {
		return
	}
	if (useState().selectOps.value[model.id]) {
		load_data_model(model.id, url, routeKy as string,true,() => {
	    show_content.value = false
		  show_message(MessageType.Success, `${t('saveload.dataLoaded','Data loaded')}`,2000,() => { 
	      show_content.value = true
			})
		})
  }
}
const onDataView = (ky: string) => {
	show_data.value[ky] = ! show_data.value[ky] 
}
const onHelp = (ky: string) => {
	show_help.value[ky] = ! show_help.value[ky] 
}
const onViewInput = (ky: string) => {
	show_inputText.value[ky] = ! show_inputText.value[ky]
}
const onSaveUser = (ky: string) => {
	const key = ky.replace('sec_','')
	let data = {} as UsersDataType
	if (usersData.value[key]) {
    data[key] = usersData.value[key]
	} else {
    data = usersData.value
	}
	saveData('send',ky ,data)
}
const load_vars_user = async (): Promise<[any,string]> => {
	const url = useState().CONFURLS.value.varsuser || ''
	if (url.length == 0)
		return [{},'No URL defined']
	let text = ''
	let res: any = {}
	let error = null
	try {
		const response = await self.fetch(url, {
			method: 'GET',
		})
		if (url.includes('.json')) {
			res = await response.json()
		} else {
      text = await response.text()
		}
		if (response.ok) {
			if (url.includes('.yaml')) {
				res = YAML.parse(text)
			} else if (!url.includes('.json')) {
				res = text
			}
		} else {
			error = res.message
		}
	}
	catch (err: any) {
		error = err.message
	}
	if (error) {
		show_message(MessageType.Error, `'Vars User Load' -> ${error}`, 5000)
		useState().connection.value.state = 'connection.error'
		return [{}, error]
	}
	return [res,error]
}
const get_users_data = async (): Promise<[any,string]> => {
	const url = useState().CONFURLS.value.users || ''
	if (url.length == 0)
		return [{},'No SRV URL defined']
	const [res,errmsg] =	await fetch_json(url, 2000,true) 
	if (errmsg.length > 0) {
		return [{},errmsg]
	}
	return [res,errmsg]
}
onBeforeMount(async() => {
	//if (Object.keys(useState().varsUser.value).length === 0) {
    const [resvars, err]  = await load_vars_user()
	  if (err && err.length > 0) {
		  show_content.value = false
		} else {
      varsUser.value = resvars
			useState().dataSections.value = []
			Object.keys(resvars).forEach(ky => {
				useState().dataSections.value.push(ky)
				show_data.value[ky] = true
				show_inputText.value[ky] = false
	      show_help.value[ky] = false
			})
		}
	//}
	const [res,errmsg] =	await get_users_data()
	if (errmsg && errmsg.length > 0) {
		debugger
		show_content.value = false
	} else {
    usersData.value = {} as UsersDataType
    usersAccounts.value = {} as UsersAccountsType
    invitations.value = {} as UsersInvitationsType
    modelsUsers.value = {} as ModelsUsersType
		if (res.data) {
			dataKeys.forEach(ky => {
				if (res.data[ky]) {
					usersData.value[ky]= b64_to_utf8(res.data[ky])
					try {
						switch(ky) {
							case 'usersData':
								usersAccounts.value = YAML.parse(usersData.value[ky])
								break
							case 'modelsData':
								modelsUsers.value = YAML.parse(usersData.value[ky])
								break
							case 'invitations':
								invitations.value = YAML.parse(usersData.value[ky])
								break
						}
					} catch(e) {
						show_message(MessageType.Error, `'Error parse data' -> ${e}`, 5000)
						useState().connection.value.state = 'data.error'
					}
				} else {
					show_data.value[ky] = false
				}
			})
		}
	}
	track_action(null, { ref: 'users',text: 'users data'}, 'mount')
})
</script>