//
//  FocusedAttachmentController.swift
//  ComposeUI
//
//  Created by Shadowfacts on 4/29/23.
//

import SwiftUI
import MatchedGeometryPresentation
import AVKit

class FocusedAttachmentController: ViewController {
    
    unowned let parent: ComposeController
    let attachment: DraftAttachment
    let thumbnailController: AttachmentThumbnailController
    private let player: AVPlayer?
    
    init(parent: ComposeController, attachment: DraftAttachment, thumbnailController: AttachmentThumbnailController) {
        self.parent = parent
        self.attachment = attachment
        self.thumbnailController = thumbnailController
        
        if case let .file(url, type) = attachment.data,
           type.conforms(to: .movie) {
            self.player = AVPlayer(url: url)
            self.player!.isMuted = true
        } else {
            self.player = nil
        }
    }
    
    var view: some View {
        FocusedAttachmentView(attachment: attachment)
    }
    
    struct FocusedAttachmentView: View {
        @ObservedObject var attachment: DraftAttachment
        @EnvironmentObject private var controller: FocusedAttachmentController
        @Environment(\.dismiss) private var dismiss
        @FocusState private var textEditorFocused: Bool
        @EnvironmentObject private var matchedGeomState: MatchedGeometryState
        
        var body: some View {
            VStack(spacing: 0) {
                Spacer(minLength: 0)
                
                if let player = controller.player {
                    VideoPlayer(player: player)
                        .matchedGeometryDestination(id: attachment.id)
                        .onAppear {
                            player.play()
                        }
                } else if #available(iOS 16.0, *) {
                    ZoomableScrollView {
                        attachmentView
                            .matchedGeometryDestination(id: attachment.id)
                    }
                } else {
                    attachmentView
                        .matchedGeometryDestination(id: attachment.id)
                }
                
                Spacer(minLength: 0)
                
                FocusedAttachmentDescriptionView(attachment: attachment)
                    .environment(\.colorScheme, .dark)
                    .matchedGeometryDestination(id: AttachmentDescriptionTextViewID(attachment))
                    .frame(height: 150)
                    .focused($textEditorFocused)
            }
            .background(.black)
            .overlay(alignment: .topLeading, content: {
                Button {
                    // set the mode to dismissing immediately, so that layout changes due to the keyboard hiding
                    // (which happens before the dismiss animation controller starts running) don't alter the destination frames
                    if textEditorFocused {
                        matchedGeomState.mode = .dismissing
                    }
                    dismiss()
                } label: {
                    Image(systemName: "arrow.down.forward.and.arrow.up.backward")
                }
                .buttonStyle(DismissFocusedAttachmentButtonStyle())
                .padding([.top, .leading], 4)
            })
        }
        
        private var attachmentView: some View {
            ControllerView(controller: { controller.thumbnailController })
                .environment(\.attachmentThumbnailConfiguration, .init(contentMode: .fit, fullSize: true))
        }
    }
}

private struct DismissFocusedAttachmentButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        ZStack {
            RoundedRectangle(cornerRadius: 4)
                .fill(.black.opacity(0.5))
            
            configuration.label
                .foregroundColor(.white)
                .imageScale(.large)
        }
        .frame(width: 40, height: 40)
    }
}

struct AttachmentDescriptionTextViewID: Hashable {
    let attachmentID: UUID!
    
    init(_ attachment: DraftAttachment) {
        self.attachmentID = attachment.id
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(attachmentID)
        hasher.combine("descriptionTextView")
    }
}

