<!DOCTYPE html>
<html>
  <title>SpaSca : Spatial Scaffolding</title>
  <head>
    <!-- Suggestions? https://git.benetou.fr/utopiah/text-code-xr-engine/issues/ -->

    <!--<script src='dependencies/aframe.min.js'></script>-->
    <script src='dependencies/aframe.offline.min.js'></script>
    <script src="dependencies/a-console.js"></script>
    <script src='dependencies/aframe-html.js'></script>
    <script src='dependencies/aframe-mirror.js'></script>
    <script src='dependencies/aframe-troika-text.min.js'></script>
    <!--<script type="module" id=immersbundle src='dependencies/immers-client.js?save=true'></script>-->
    <!--<script type="module" id=immersbundle src="https://cdn.jsdelivr.net/npm/immers-client/dist/destination.bundle.js?role=modFull"></script>-->
    <!--<script src="https://threejs.org/examples/js/exporters/GLTFExporter.js"></script>-->

    <script src="https://cdn.jsdelivr.net/gh/c-frame/aframe-extras@7.1.0/dist/aframe-extras.min.js"></script>

    <script src="dependencies/shiki0.14.1.js"></script>

    <!-- for input sharing -->
    <script src='dependencies/peerjs.min.js'></script>
    <!-- for content sharing, using NAF 
    <script src='dependencies/socket.io.slim.js'></script>
    <script src="https://naf.benetou.fr/easyrtc/easyrtc.js"></script>
    <script src='dependencies/networked-aframe.min.js'></script>
    -->

    <script src="dependencies/aframe-physics-system.min.js"></script>

    <!-- still experimenting, see webdav.html -->
    <script src='dependencies/webdav.js'></script> 
    
    <script src='jxr.js?12345'></script> 
    <!-- replacing with local copies as CDNs are like unpkg tend to be slow
    <script type="module" src="https://unpkg.com/immers-client/dist/destination.bundle.js"></script>
    <script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>

    <script src="https://unpkg.com/aframe-troika-text/dist/aframe-troika-text.min.js"></script>
    <script src="aframe-html.js"></script>

    <script src="https://unpkg.com/peerjs@1.4.5/dist/peerjs.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.4.0/socket.io.slim.js"></script>
    <script src="https://naf.benetou.fr/easyrtc/easyrtc.js"></script>
    <script src="https://unpkg.com/networked-aframe@^0.10.0/dist/networked-aframe.min.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/aframe-mirror@latest/index.js"></script>
	 -->

    <link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
    <link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png">
    <link rel="manifest" href="site.webmanifest">
  </head>
  <body>

<script>
/*
motivated composability sketches done the 29/3/2024 with igloo example

see past branches indluding
  bind-jxr-target
  gltf-jxr
but also possibly
  visual-tension
  nodal
ideally not full on editors e.g
  editor-split

highlight could start as 
	x use a jxr command to pre-select an existing jxr snippet (already exists somewhere in past work, at least for classes...)
	x place a cursor e.g | at the beginning of the snippet copied in the feedback HUD
	x moving the index along the x axis moves the cursor within that snippet on HUD
	x pinching starts the selection, all characters within that selected are bolden
	x 	if not (yet) supported by troika then consider another color, e.g unselected text as white, selected as grey
	x releasing the pinch complete the selection
	new affordance can thus be proposed as jxr snippets applying not to the entire jxr snippet pre-selected but selection only

cf e.g

	tensionVisualized()
*/

// generalized version of past onNextPinchSplitReader()
function onNextPinch(callback){
	let lastPrimary = selectedElements.filter( e => e.primary ).length
	let checkForNewPinches = setInterval( _ => {
		if (selectedElements.filter( e => e.primary ).length > lastPrimary){
			let id = getIdFromPick() // applies on primary only
			if (id) { callback(id) }
			clearInterval(checkForNewPinches)
		}
	}, 50) // relatively cheap check, filtering on small array
}

let selection = ''
function highlightSnippet(id){
	let value = document.getElementById(id).getAttribute('value')
	// perdiodically check on x position of left index and move | accordingly

        let p = document.querySelector('[pinchprimary]')
        let target = new THREE.Vector3(); // create once an reuse it
	let currentCharPos = -1
	let pinchStartedPos = -1
	let pinchEndedPos = -1
        p.addEventListener('pinchstarted', event => { pinchEndedPos = -1; pinchStartedPos = currentCharPos } )
        p.addEventListener('pinchended', event => pinchEndedPos = currentCharPos)
        let indexTipTracking = setInterval( _ => {
		target = p.components['hand-tracking-controls'].indexTipPosition
		let position = target.x * 100 // should use relative position but easier to start with
		currentCharPos = position
		let nvalue = value.slice(0,position) + '|' + value.slice(position)
		// setFeedbackHUD( nvalue ) not good as it autoclears after
		// console.log(pinchStartedPos, pinchEndedPos)
		// should offset based on past modification
		if (pinchStartedPos>-1) nvalue = nvalue.slice(0,pinchStartedPos) + '<' + nvalue.slice(pinchStartedPos)
		if (pinchEndedPos>-1) nvalue = nvalue.slice(0,pinchEndedPos) + '>' + nvalue.slice(pinchEndedPos)
		document.querySelector("#feedbackhud").setAttribute("value",nvalue)
		// works but could also consider cloning the initial element from id then moving it slight forward and changing color on the cloned one
		let newSelection = ''
		if (pinchStartedPos > -1 && pinchEndedPos > -1) newSelection = value.slice(pinchStartedPos,pinchEndedPos) 
		if (newSelection.length > 0 && selection != newSelection ){
			 AFRAME.scenes[0].emit( 'selectionchanged' , {id: id, selection: newSelection} )
			// works... yet emits on pinchstarted too 
			selection = newSelection
		}

	}, 20)

}

AFRAME.registerComponent('onselectionchange', {
  schema: {
    // callback: {type: 'string', default: console.log }, // doubt functions can be a type
  },
  init: function(){
	let generatorName = this.attrName
	AFRAME.scenes[0].addEventListener('selectionchanged', event => console.log( 'selected text in snippet', event.detail.id, ':',  event.detail.selection ) )
	// here console.log could be callback
  }
})

</script>
<input style='position:fixed;z-index:1; top: 0%; left: 20%; display:float' 
	type="file" name="file-input" accept=".json"  id="file-input" onchange="loadFile(this)" />
<div style='position:fixed;z-index:1; top: 0%; left: 0%; border-bottom: 70px solid transparent; border-left: 70px solid #eee; '>
	<a href="https://git.benetou.fr/utopiah/text-code-xr-engine/issues/">
		<img style='position:fixed;left:10px;' title='code repository' src='gitea_logo.svg'>
	</a>
</div>

<button id=mainbutton style="display:none; z-index: 1; position: absolute; width:50%; margin: auto; text-align:center; top:45%; left:30%; height:30%;" onclick="startExperience()">Start the experience (hand tracking recommended)</button>

<a-scene startfunctions onselectionchange>
	<!-- screenstack dynamic-view selectionboxonpinches glossary timeline issues fot
	toolbox commands-from-external-json disable-components-via-url enable-components-via-url 
	physics="debug:true; friction: 0.01;" 
	networked-scene="serverURL: https://naf.benetou.fr/; adapter: easyrtc; audio: true;"
	refresh-text-content-from-wiki-page="pagename:TestingPairCollaboration"
	-->
      <a-assets>
	      <template id="avatar-template"></template>
	      <template id="left-hand-default-template">
		      <a-entity networked-hand-controls="hand:left"></a-entity>
	      </template>
	      <template id="right-hand-default-template">
		      <a-entity networked-hand-controls="hand:right"></a-entity>
	      </template>
      </a-assets>

      <a-gltf-model hide-on-enter-ar="" src="../content/MinimalisticJapaneseRoom.glb" rotation="0 -90 0" position="2 1 -1" scale="" ></a-gltf-model>
	<!-- from https://poly.pizza/m/8cWuXx5BASV -->
	<!-- alt https://poly.pizza/m/cA_lcvRC4NA -->

      <a-troika-text anchor=left target annotation="content:could be used to then edit that snippet"
	value="jxr onNextPinch(setFeedbackHUD)" position=" -0.3 0.60 -.5" rotation="0 0 0" scale="0.1 0.1 0.1"></a-troika-text>

      <a-troika-text anchor=left target annotation="content:then edit that snippet"
	value="jxr onNextPinch(highlightSnippet)" position=" -0.3 1.20 -.5" rotation="0 0 0" scale="0.1 0.1 0.1"></a-troika-text>

      <a-troika-text anchor=left target annotation="content:refresh page while keeping XR on"
	value="jxr location.reload()" position=" -0.3 1.50 -.5" rotation="0 0 0" scale="0.1 0.1 0.1"></a-troika-text>

      <a-entity id="rig">
		<a-entity id="player" networked="template:#avatar-template;attachTemplateToLocal:false;" 
			hud camera look-controls wasd-controls waistattach="target: .movebypinch" position="0 1.6 0">
		</a-entity>
		<a-entity id="rightHand" pinchprimary hand-tracking-controls="hand: right;"></a-entity>
		<a-entity id="leftHand" pinchsecondary wristattachsecondary="target: #box" hand-tracking-controls="hand: left;"></a-entity>
      </a-entity>

      <a-box pressable start-on-press id="box" scale="0.05 0.05 0.05" color="pink"></a-box>
      <!-- could attach functions here... BUT then they have to be activable with the other hand! -->
      <!-- visual reminders of shortcuts, a poster on the far left/right of keyboard shortcuts -->

      <a-entity light="type: ambient; color: #BBB; intensity: 0.6"></a-entity>
      <a-entity light="type: directional; color: #FFF; intensity: 1.4" position="-0.5 1 1"></a-entity>

      <a-troika-text value="SpaSca : Spatial Scaffolding" anchor="left" outline-width="5%" font="../content/ChakraPetch-Regular.ttf" position="-5.26197 6.54224 -1.81284"
	scale="4 4 5" rotation="90 0 0" troika-text="outlineWidth: 0.01; strokeColor: #ffffff" material="flatShading: true; blending: additive; emissive: #c061cb"></a-troika-text>
      <a-sky hide-on-enter-ar color="lightgray"></a-sky>
      <a-troika-text anchor=left target value="instructions : \n--right pinch to move\n--left pinch to execute" position="0 0.65 -0.2" scale="0.1 0.1 0.1"></a-troika-text>
      
      <!-- 
      <a-troika-text anchor=left target id="startdraw2d" annotation="content:dessiner en 2D"
		value="jxr startDraw2D()" position="0 1.45 -0.1" scale="0.1 0.1 0.1"></a-troika-text>

      <a-troika-text anchor=left target id="displaypred" value="jxr displayPred()" position="0 1.40 -0.1" scale="0.1 0.1 0.1"></a-troika-text>
      <a-troika-text anchor=left target value="jxr tiltUpId('codeditor')" position=" -0.3 1.65 0" rotation="0 90 0" scale="0.1 0.1 0.1"></a-troika-text>
      <a-troika-text anchor=left target value="jxr tiltDownId('codeditor')" position=" -0.3 1.60 0" rotation="0 90 0" scale="0.1 0.1 0.1"></a-troika-text>
	-->

      <!-- somehow disable hand interaction despite, according to the documentation, it should rely on world position 
	      <a-text target value="jxr qs #rig sa position 0 0 10" position="0 1.55 .5" rotation="0 180 0" scale="0.1 0.1 0.1"></a-text>
	-->
      <a-console position="2 2 -1" rotation="0 -45 0" font-size="34" height=1 skip-intro=true></a-console>

      <!-- for Wolvic on Lynx support test -->
      <a-entity thumbstick-shifting oculus-touch-controls="hand: left"></a-entity>
      <a-entity thumbstick-shifting oculus-touch-controls="hand: right"></a-entity>

    </a-scene>
  </body>
</script>
</html>