//
//  DropScene.swift
//  BookCore
//
//  Created by 日々野清高 on 2021/03/26.
//

import Foundation
import SpriteKit
import AVFoundation

enum ThrusterFailure {
    case left
    case right
}

class MoveScene: SKScene, SKPhysicsContactDelegate {
    weak var moveSceneDelegate: MoveSceneDelegate? // 追加
    var backgroundMusicPlayer: AVAudioPlayer?
    var jewel:SKSpriteNode!
    var player:SKSpriteNode!
    var backgroundImage:SKSpriteNode!
    var floorImage:SKSpriteNode!
    var backgroundMusic:SKAudioNode!
    var wSound:SKAudioNode!
    var mSound:SKAudioNode!
    var gSound:SKAudioNode!
    var dropWait:Bool = false
    let Box: UInt32 = 1 << 1
    public override func didMove(to view: SKView) {
        //サウンドの準備
        prepareAudioNodes()
        //衝突デレゲートを自分に
        physicsWorld.contactDelegate = self
        // フレームサイズを、ビューの境界と同じにします。
        self.size = view.bounds.size
        // 重力の向きと強さを設定。
        self.physicsWorld.gravity = CGVector(dx: 0.0, dy: -2.4)
        // エッジを作ってノードが画面からはみ出さないようにします。
        self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
        self.physicsBody?.restitution = 0.0 //弾性係数
        self.name = "scene"
        //シーンの背景色
        self.backgroundColor = SKColor.gray
        let bg = SKSpriteNode(imageNamed: "background2.png")
        createStars(count: 100) // 100個の星を追加
        backgroundImage = bg
        backgroundImage.size = CGSize(width: 200, height: 200)
        backgroundImage.position = CGPoint(x: size.width/2, y: size.height/2)
        backgroundImage.zPosition = -10
        addChild(backgroundImage)
        playBackgroundMusic()
    }
    
    func playBackgroundMusic() {
        guard let musicURL = Bundle.main.url(forResource: "backgroundMusic", withExtension: "mp3") else {
            print("音楽ファイルが見つかりません")
            return
        }

        do {
            backgroundMusicPlayer = try AVAudioPlayer(contentsOf: musicURL)
            backgroundMusicPlayer?.numberOfLoops = -1 // ループ再生
            backgroundMusicPlayer?.volume = 0.5       // 音量調整（0.0〜1.0）
            backgroundMusicPlayer?.play()
        } catch {
            print("音楽の再生に失敗しました: \(error)")
        }
    }
    
    func toggleMusic(isOn: Bool) {
        if isOn {
            backgroundMusicPlayer?.play()
        } else {
            backgroundMusicPlayer?.pause()
        }
    }
    
    private func prepareAudioNodes() {
        DispatchQueue.global().async {
            let cs1 = SKAudioNode(fileNamed: "warp.mp3")
            let cs2 = SKAudioNode(fileNamed: "spray.mp3")
            let cs3 = SKAudioNode(fileNamed: "gate.mp3")
            DispatchQueue.main.async {
                self.wSound = cs1
                self.wSound.autoplayLooped = false
                self.mSound = cs2
                self.mSound.autoplayLooped = false
                self.gSound = cs3
                self.gSound.autoplayLooped = false
                self.addChild(self.wSound)
                self.addChild(self.mSound)
                self.addChild(self.gSound)
            }
        }
    }
    
    override var isUserInteractionEnabled: Bool {
        get {
            return true
        }
        set {
            // ignore
        }
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        /*for touch: AnyObject in touches {
         let location = touch.location(in: self)
         let jewel = SKSpriteNode(imageNamed: "jewel11.png")
         jewel.size = CGSize(width: 20, height: 20)
         if(!dropWait) {
         dropFrame(Int(location.x / 20) + 1)
         dropWait = true
         let seconds = 0.16
         DispatchQueue.main.asyncAfter(deadline: .now() + seconds) {
         // Put your code which should be executed with a delay here
         self.dropWait = false
         }
         return
         }
         }*/
    }
    
    public override func update(_ currentTime: CFTimeInterval) {}
    
    public func placeNode(_ x: Int, _ y: Int, imageName: String, warpId: Int? = nil) {
        let sknode = SKSpriteNode(imageNamed: imageName)
        sknode.name = imageName
        sknode.size = CGSize(width: 20, height: 20)
        
        // 物理ボディの設定
        if imageName == "warpIn" || imageName == "warpOut" {
            sknode.physicsBody = SKPhysicsBody(circleOfRadius: sknode.size.width / 2)
            sknode.physicsBody?.categoryBitMask = 0x1 << 3  // WARPカテゴリ
            sknode.physicsBody?.collisionBitMask = 0 // 衝突なし
            sknode.physicsBody?.contactTestBitMask = 0x1 << 1 // プレイヤーとの接触のみ検出
            // warpIn, warpOut の場合に userData を設定
            if let id = warpId {
                sknode.userData = NSMutableDictionary()
                sknode.userData?["id"] = id
            }
        } else {
            sknode.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 20, height: 20))
            sknode.physicsBody?.categoryBitMask = Box
        }
        
        sknode.position = CGPoint(x: CGFloat(x * 20) - 10, y: CGFloat(y * 20) - 10)
        sknode.physicsBody?.isDynamic = false
        sknode.physicsBody?.affectedByGravity = false
        sknode.physicsBody?.contactTestBitMask = 0xFFFFFFFF

        // GOALの設定
        if imageName == "goal" {
            let earthTextures = [
                SKTexture(imageNamed: "earth01"),
                SKTexture(imageNamed: "earth02"),
                SKTexture(imageNamed: "earth03"),
                SKTexture(imageNamed: "earth04"),
                SKTexture(imageNamed: "earth05"),
                SKTexture(imageNamed: "earth06"),
                SKTexture(imageNamed: "earth07"),
                SKTexture(imageNamed: "earth08"),
                SKTexture(imageNamed: "earth09"),
                SKTexture(imageNamed: "earth10"),
                SKTexture(imageNamed: "earth11"),
                SKTexture(imageNamed: "earth12")
            ]
            let animationAction = SKAction.animate(with: earthTextures, timePerFrame: 0.5)
            let repeatAnimation = SKAction.repeatForever(animationAction)
            sknode.physicsBody?.categoryBitMask = 0x1 << 2  // GOALカテゴリ
            sknode.physicsBody?.collisionBitMask = 0    // 衝突を無効化
            sknode.physicsBody?.contactTestBitMask = 0  // 不要なら無効化
            sknode.run(repeatAnimation)
        }

        // 隕石の動き
        if imageName == "asteroid" {
            let asteroidTextures = [
                SKTexture(imageNamed: "asteroid01"),
                SKTexture(imageNamed: "asteroid02")
            ]
            
            // スプライトのアニメーション
            let animationAction = SKAction.animate(with: asteroidTextures, timePerFrame: 1)
            let repeatAnimation = SKAction.repeatForever(animationAction)
            
            // 隕石の移動アニメーション（ランダムな動き）
            let moveX = CGFloat.random(in: -1...1)
            let moveY = CGFloat.random(in: -1...1)
            let moveAction = SKAction.moveBy(x: moveX, y: moveY, duration: 4.0)
            let reverseAction = moveAction.reversed()
            let moveSequence = SKAction.sequence([moveAction, reverseAction])
            let repeatMove = SKAction.repeatForever(moveSequence)
            
            // 両方のアクションを並行して実行
            let groupAction = SKAction.group([repeatAnimation, repeatMove])
            sknode.name = "asteroid"
            sknode.run(groupAction)
        }
        //  warpホールの回転アクション
        if imageName == "warpIn" {
            let rotateAction = SKAction.rotate(byAngle: .pi / 2, duration: 1.0)
            let repeatAction = SKAction.repeatForever(rotateAction)
            sknode.run(repeatAction)
        } else if imageName == "warpOut" {
            let rotateAction = SKAction.rotate(byAngle: .pi / -2, duration: 1.0)
            let repeatAction = SKAction.repeatForever(rotateAction)
            sknode.run(repeatAction)
        }

        // **プレイヤーの設定**
        if imageName == "player" {  // ← sknode.name ではなく imageName を使用
            player = sknode
            player.zPosition = 100 // 前面に表示
            player.physicsBody = SKPhysicsBody(circleOfRadius: player.size.width / 2)
            player.physicsBody?.isDynamic = true
            player.physicsBody?.affectedByGravity = false
            player.physicsBody?.categoryBitMask = 0x1 << 1  // PLAYERカテゴリ
            player.physicsBody?.contactTestBitMask = 0xFFFFFFFF
            player.physicsBody?.collisionBitMask = 0xFFFFFFFF  & ~(0x1 << 2) & ~(0x1 << 3) // GOALとwarpとの衝突を除外
        }
        self.addChild(sknode)
    }


    // 左に90度回転
    func playerLeft() {
        // ジェット噴射の画像に切り替え
        player.texture = SKTexture(imageNamed: "player_left.png")
        
        // 回転アニメーションを実行
        let rotateLeft = SKAction.rotate(byAngle: CGFloat.pi / 2, duration: 0.2)
        
        // 回転後に元の画像に戻すアクション
        let resetTexture = SKAction.run {
            self.player.texture = SKTexture(imageNamed: "player.png")
        }
        let playSound = SKAction.run { [weak self] in
            self?.mSound.run(SKAction.play())
        }
        let stopSound = SKAction.run { [weak self] in
            self?.mSound.run(SKAction.stop())
        }
        // 回転アニメーションとテクスチャ変更を連続して実行
        let actionSequence = SKAction.sequence([playSound, rotateLeft, resetTexture, stopSound])
        player.run(actionSequence)
    }
    
    // 右に90度回転
    func playerRight() {
        // ジェット噴射の画像に切り替え
        player.texture = SKTexture(imageNamed: "player_right.png")
        let rotateRight = SKAction.rotate(byAngle: -CGFloat.pi / 2, duration: 0.2)
        let resetTexture = SKAction.run {
            self.player.texture = SKTexture(imageNamed: "player.png")
        }
        let playSound = SKAction.run { [weak self] in
            self?.mSound.run(SKAction.play())
        }
        let stopSound = SKAction.run { [weak self] in
            self?.mSound.run(SKAction.stop())
        }
        let actionSequence = SKAction.sequence([playSound, rotateRight, resetTexture, stopSound])
        player.run(actionSequence)
    }
    
    //前に進める（スラスター故障オプション付き）
    func playerForward(thrusterFailure: ThrusterFailure? = nil) {
        let angle = player.zRotation
        let moveDistance: CGFloat = 20.0  // 1マス分の距離
        player.texture = SKTexture(imageNamed: "player_move.png")

        // 移動する方向を計算（Y軸が下向きなので調整）
        let dx = -sin(angle) * moveDistance
        let dy = cos(angle) * moveDistance

        let moveAction = SKAction.moveBy(x: dx, y: dy, duration: 0.2)

        // スラスター故障時の回転アクション
        let rotateAction: SKAction
        switch thrusterFailure {
        case .left:
            rotateAction = SKAction.rotate(byAngle: CGFloat.pi / 2, duration: 0.2)
            player.texture = SKTexture(imageNamed: "player_left.png")
        case .right:
            rotateAction = SKAction.rotate(byAngle: -CGFloat.pi / 2, duration: 0.2)
            player.texture = SKTexture(imageNamed: "player_right.png")
        case .none:
            rotateAction = SKAction.rotate(byAngle: 0, duration: 0.2) // 回転なし
        }

        // 並列実行（前進と回転を同時に）
        let moveAndRotate = SKAction.group([moveAction, rotateAction])

        // ゴール判定アクション
        let checkGoalAction = SKAction.run { [weak self] in
            guard let self = self else { return }
            if let goal = self.childNode(withName: "goal") {
                let intersection = self.player.frame.intersection(goal.frame)
                let overlapArea = intersection.width * intersection.height
                let playerArea = self.player.frame.width * self.player.frame.height
                let overlapRatio = overlapArea / playerArea
                if overlapRatio > 0.9 {  // 90%以上重なったらゴール
                    self.handleGoalReached()
                }
            }
        }
        
        // ワープ判定アクション
        let checkWarpAction = SKAction.run { [weak self] in
            self?.checkWarp()
        }
        
        let resetTexture = SKAction.run { [weak self] in
            self?.player.texture = SKTexture(imageNamed: "player.png")
        }
        let playSound = SKAction.run { [weak self] in
            self?.mSound.run(SKAction.play())
        }
        let stopSound = SKAction.run { [weak self] in
            self?.mSound.run(SKAction.stop())
        }

        // アクションのシーケンスを作成
        let actionSequence = SKAction.sequence([
            playSound,
            moveAndRotate,  // ここで前進と回転を同時に実行
            checkGoalAction,
            checkWarpAction,
            resetTexture,
            stopSound
        ])

        // アクションを実行
        player.run(actionSequence)
    }

    // GOALに到達した際の処理
    func handleGoalReached() {
        wSound.run(SKAction.play())
        let shrinkAction = SKAction.scale(to: 0.0, duration: 0.5) // サイズを0に縮小
        let fadeAction = SKAction.fadeOut(withDuration: 0.5) // フェードアウト
        let removeAction = SKAction.removeFromParent() // シーンから削除
        let groupAction = SKAction.group([shrinkAction, fadeAction]) // 両方同時に実行
        let sequence = SKAction.sequence([groupAction, removeAction]) // その後削除

        player.run(sequence)
        // ここにクリア演出や次のステージ処理を追加
        // デリゲートを通じて通知
        moveSceneDelegate?.didReachGoal()
        
    }
    
    func checkWarp() {
        for node in self.children {
            if let warpInNode = node as? SKSpriteNode, warpInNode.name == "warpIn" {
                let intersection = self.player.frame.intersection(warpInNode.frame)
                let overlapArea = intersection.width * intersection.height
                let playerArea = self.player.frame.width * self.player.frame.height
                let overlapRatio = overlapArea / playerArea

                if overlapRatio > 0.9, let warpId = warpInNode.userData?["id"] as? Int {
                    // 90%以上重なったらワープ
                    gSound.run(SKAction.play())
                    let shrinkAndRotate = SKAction.group([
                        SKAction.scale(to: 0.001, duration: 0.2),  // 小さくする
                        SKAction.rotate(byAngle: .pi * 2, duration: 0.2), // 1回転
                        SKAction.fadeAlpha(to: 0.0, duration: 0.2)
                    ])

                    let warpAction = SKAction.run { [weak self] in
                        self?.warpPlayer(warpId: warpId)
                    }

                    let sequence = SKAction.sequence([shrinkAndRotate, warpAction])
                    player.run(sequence)
                    break
                }
            }
        }
    }

    func warpPlayer(warpId: Int) {
        let warpOutNodes = self.children.compactMap { node -> SKSpriteNode? in
            guard let spriteNode = node as? SKSpriteNode, spriteNode.name == "warpOut",
                  let nodeWarpId = spriteNode.userData?["id"] as? Int, nodeWarpId == warpId else {
                return nil
            }
            return spriteNode
        }
        
        guard let warpOutNode = warpOutNodes.randomElement() else { return }

        // 位置を即座に変更
        self.player.position = warpOutNode.position
        self.player.isHidden = false // ワープ後に表示
        self.player.alpha = 1.0      // 透明度をリセット
        self.player.setScale(1.0)    // スケールをリセット
    }



    
    //衝突検出
    func didBegin(_ contact: SKPhysicsContact) {
        //AudioServicesPlaySystemSound(soundIdRing)
        if contact.bodyA.node?.name == "scene" || contact.bodyB.node?.name == "scene" {
            return
        }
        if (contact.bodyA.node?.name == "jewel" && contact.bodyB.node?.name == "jewel") {
            wSound.run(SKAction.stop())
            wSound.run(SKAction.play())
        }
    }
    
    //ノードを消去する処理
    public func clear() {
        // `backgroundImage` と `wSound` を除くノードを削除
        for node in children {
            if node !== backgroundImage && node !== mSound && node !== wSound && node !== gSound && node.name != "star" && node.name != "asteroid" {
                node.removeFromParent()
            }
        }
    }
    
    public func createStars(count: Int) {
        for _ in 0..<count {
            let star = SKShapeNode(circleOfRadius: CGFloat.random(in: 0.05...0.1)) // 1〜3ドットに調整
            star.fillColor = .blue
            star.isUserInteractionEnabled = false
            star.zPosition = -1  // 背景として最背面に配置
            star.position = CGPoint(
                x: CGFloat.random(in: 0...size.width),
                y: CGFloat.random(in: 0...size.height)
            )
            star.alpha = 0.3 // 初期は少し薄めに
            star.name = "star" // 星であることを識別
            // 星の瞬きを設定（ランダムな時間でフェードイン・アウト）
            let fadeIn = SKAction.fadeAlpha(to: 1.0, duration: Double.random(in: 2.0...4.0))
            let fadeOut = SKAction.fadeAlpha(to: 0.3, duration: Double.random(in: 2.0...4.0))
            let sequence = SKAction.sequence([fadeIn, fadeOut])
            let repeatAction = SKAction.repeatForever(sequence)
            star.run(repeatAction)
            addChild(star) // シーンに追加
        }
    }
}
