//#-hidden-code
//
//  See LICENSE folder for this template’s licensing information.
//
//  Abstract:
//  The Swift file containing the source code edited by the user of this playground book.
//
import ARKit
import SceneKit
import PlaygroundSupport
import AVFoundation
import AudioToolbox

class ViewController: UIViewController, ARSCNViewDelegate, UIGestureRecognizerDelegate {
//#-end-hidden-code
/*: some text
##  🖼️AR写真を作ろう
AR(拡張現実）のプログラムを体験しよう\
🔸ARカメラとして動作するプログラムです。\
🔸［▶︎コードを実行］ボタンを押すと、最初にカメラへのアクセスが求められるので、［OK］ボタンで許可してください。\
🔸きっかけの画像(myImage)と再生する動画(myVideo)を設定して、オリジナルのARカメラを作りましょう。
 * Important:
写真は、カメラロールに入っていれば変更できます。\
動画は、カメラロールからファイルとして保存しておく必要があります。\
必要に応じて、各種パラメーターを調整してください。
---
*/
//#-code-completion(everything, hide)
//#-editable-code
//きっかけの画像
let myImage = UIImage(#imageLiteral(resourceName: "image01.jpg"))
//再生する動画
let myVideo = AVPlayerItem(url: #fileLiteral(resourceName: "movie01.mov"))
//必要に応じて調整するパラメーター
//ビデオサイズ調整（反転はマイナス）
let yScale = -0.8
let xScale = 0.6
//明るさの調整（-1.0から1.0まで）
let brightness = -0.2
//サウンドの音量
let volume = 0.5
//ビデオを繰り返し再生の可否
let repeating = false
//#-end-editable-code
//#-hidden-code
    let sceneView = ARSCNView(frame: .zero)
    var trackingImages = Set<ARReferenceImage>()
    var planeNode = SCNNode()
    var player = AVPlayer()
    var videoScene = SKScene()
    var playButtonNode = SCNNode()
    var imageMaterial = SCNMaterial()
    let button_image = UIImage(named: "play_button.png")
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view = self.sceneView
        sceneView.delegate = self
        sceneView.scene = SCNScene()
        sceneView.autoenablesDefaultLighting = true
        self.imageTrackingConfig()
        
        let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(tap(_:)))
        tapRecognizer.delegate = self
        sceneView.addGestureRecognizer(tapRecognizer)
        
        player = AVPlayer(playerItem: myVideo)
        player.volume = Float(self.volume)
        player.actionAtItemEnd = .none
        // ループ再生のために通知を設定
        NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidReachEnd(_:)), name: .AVPlayerItemDidPlayToEndTime, object: nil)
        
        let size = CGSize(width: 720, height: 576)
        videoScene = SKScene(size: size)
        let videoNode = SKVideoNode(avPlayer: player)
        videoNode.name = "video"
        videoNode.position = CGPoint(x: size.width / 2, y: size.height / 2)
        videoNode.yScale = yScale
        videoNode.xScale = xScale
        //videoScene.addChild(videoNode)
        videoScene.backgroundColor = .clear
        // Apply filter to the scene (for global brightness adjustment)
        let brightnessFilter = CIFilter(name: "CIColorControls")
        brightnessFilter?.setValue(brightness, forKey: kCIInputBrightnessKey) // Adjust brightness here
        let effectNode = SKEffectNode()
        effectNode.filter = brightnessFilter
        effectNode.addChild(videoNode)
        videoScene.addChild(effectNode)
        videoScene.isHidden = true //最初は非表示
        
        // 再生ボタンのSCNNodeを作成します
        imageMaterial.diffuse.contents = button_image // 画像をdiffuse.contentsに設定します
        imageMaterial.isDoubleSided = true// マテリアルが両面を表示するように設定します
        //imageMaterial.transparency = 0.7 // 透明度を設定します
        let imgPlane = SCNPlane(width: 1, height: 1)// SCNPlaneのサイズを調整します
        imgPlane.materials = [imageMaterial]// SCNPlaneにSCNMaterialを適用します
        playButtonNode = SCNNode(geometry: imgPlane)// SCNNodeを作成し、SCNPlaneをgeometryに設定します
        playButtonNode.scale = SCNVector3(0.04, 0.04, 0.04)// ボタンのサイズを調整します
        playButtonNode.isHidden = true// ボタンを最初は非表示にします
        // 点滅アニメーションの設定
        let fadeInAction1 = SCNAction.fadeOpacity(to: 1.0, duration: 0.01)
        let fadeInAction2 = SCNAction.fadeOpacity(to: 1.0, duration: 0.7)
        let fadeOutAction1 = SCNAction.fadeOpacity(to: 0.0, duration: 0.01)
        let fadeOutAction2 = SCNAction.fadeOpacity(to: 0.0, duration: 0.3)
        let blinkSequence = SCNAction.sequence([fadeInAction1, fadeInAction2, fadeOutAction1, fadeOutAction2])
        let blinkForever = SCNAction.repeatForever(blinkSequence)
        playButtonNode.runAction(blinkForever)
        
        self.sceneView.scene.rootNode.addChildNode(playButtonNode)
        
        //let textGeometry = SCNText(string: "▶︎", extrusionDepth: 0.1)
        //textGeometry.firstMaterial?.diffuse.contents = UIColor.white // 文字の色を設定します
        //textGeometry.firstMaterial?.transparency = 0.7 // 透明度を設定します
        //textGeometry.alignmentMode = CATextLayerAlignmentMode.center.rawValue // センタリング
        //let textNode = SCNNode(geometry: textGeometry)
        //textNode.scale = SCNVector3(0.1, 0.1, 0.1) // 文字のサイズを調整します
        //textNode.isHidden = true // 最初は非表示にします

        //self.sceneView.scene.rootNode.addChildNode(textNode)
        //self.playButtonNode = textNode
    }
    
    private func imageTrackingConfig() {
        
        let image = ARReferenceImage(myImage.cgImage!,
                                               orientation: .up,
                                             physicalWidth: 0.2)
        
        self.trackingImages.insert(image)
        
        let config = ARImageTrackingConfiguration()
        config.trackingImages = trackingImages
        self.sceneView.session.run(config)
    }
    
    // ARSCNViewDelegate
    func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        
        let node = SCNNode()
        if let imageAnchor = anchor as? ARImageAnchor {
            
            //AudioServicesPlaySystemSound(SystemSoundID(1057))
            // ARImageAnchorの位置にボタンを表示します
            self.playButtonNode.isHidden = false
            // 再生ボタンの位置を調整します
            self.updatePlayButtonPosition(anchor: imageAnchor)
            let transparentMaterial = SCNMaterial()
            transparentMaterial.diffuse.contents = UIColor.clear // 透明な色
            
            let plane = SCNPlane(width: imageAnchor.referenceImage.physicalSize.width,
                                         height: imageAnchor.referenceImage.physicalSize.height)

            plane.materials = [transparentMaterial]
            plane.firstMaterial?.diffuse.contents = videoScene
            planeNode = SCNNode(geometry: plane)
            planeNode.eulerAngles.x = -.pi / 2
            planeNode.addChildNode(playButtonNode)
            node.addChildNode(planeNode)
            //player.play()
        }
        return node
    }
    
    // ボタンの位置を更新するメソッド
    func updatePlayButtonPosition(anchor: ARImageAnchor) {
        //guard let playButtonNode = self.playButtonNode else {
        //    return
        //}
        // ビデオノードと同じサイズに設定します
        let buttonWidth = anchor.referenceImage.physicalSize.width // ボタンの幅は画像の幅の20%
        let buttonHeight = anchor.referenceImage.physicalSize.height // ボタンの高さは画像の高さの20%
        playButtonNode.position = SCNVector3(0, 0, 0.01) // 画像の上にボタンを配置します
    }
    
    //Tap Event
    @objc func tap(_ tapRecognizer: UITapGestureRecognizer) {

        let touchPoint = tapRecognizer.location(in: self.sceneView)
        
        let results = self.sceneView.hitTest(touchPoint, options: [SCNHitTestOption.searchMode : SCNHitTestSearchMode.all.rawValue])
        
        if let result = results.first {
            //AudioServicesPlaySystemSound(SystemSoundID(1057))
            //guard let hitNodeName = result.node.name else { return }
            //guard hitNodeName == "video" else { return }
            self.playButtonNode.isHidden = true
            self.videoScene.isHidden = false
            self.player.seek(to: .zero)
            self.player.play()
        }
    }
    
    @objc func playerItemDidReachEnd(_ notification: Notification) {
        if (!repeating) {
            self.videoScene.isHidden = true
            self.playButtonNode.isHidden = false
        }
        if let playerItem = notification.object as? AVPlayerItem {
            // プレイヤーを再生位置を最初に戻す
            if (repeating) {
                playerItem.seek(to: .zero, completionHandler: nil)
            }
        }
    }
}

var vc = ViewController()
PlaygroundPage.current.liveView = vc
PlaygroundPage.current.needsIndefiniteExecution = true

//#-end-hidden-code

