//
//  DraftsController.swift
//  ComposeUI
//
//  Created by Shadowfacts on 3/7/23.
//

import SwiftUI
import TuskerComponents
import CoreData

class DraftsController: ViewController {
    
    unowned let parent: ComposeController
    @Binding var isPresented: Bool
    
    @Published var draftForDifferentReply: Draft?
    
    init(parent: ComposeController, isPresented: Binding<Bool>) {
        self.parent = parent
        self._isPresented = isPresented
    }
    
    var view: some View {
        DraftsRepresentable()
    }
    
    func maybeSelectDraft(_ draft: Draft) {
        if draft.inReplyToID != parent.draft.inReplyToID,
           parent.draft.hasContent {
            draftForDifferentReply = draft
        } else {
            confirmSelectDraft(draft)
        }
    }
    
    func cancelSelectingDraft() {
        draftForDifferentReply = nil
    }
    
    func confirmSelectDraft(_ draft: Draft) {
        parent.selectDraft(draft)
        closeDrafts()
    }
    
    func deleteDraft(_ draft: Draft) {
        DraftsPersistentContainer.shared.viewContext.delete(draft)
    }
    
    func closeDrafts() {
        isPresented = false
        DraftsPersistentContainer.shared.save()
    }
    
    struct DraftsRepresentable: UIViewControllerRepresentable {
        typealias UIViewControllerType = UIHostingController<DraftsView>
        
        func makeUIViewController(context: Context) -> UIHostingController<DraftsController.DraftsView> {
            return UIHostingController(rootView: DraftsView())
        }
        
        func updateUIViewController(_ uiViewController: UIHostingController<DraftsController.DraftsView>, context: Context) {
        }
    }
    
    struct DraftsView: View {
        @EnvironmentObject private var controller: DraftsController
        @EnvironmentObject private var currentDraft: Draft
        @FetchRequest(sortDescriptors: [SortDescriptor(\Draft.lastModified, order: .reverse)]) private var drafts: FetchedResults<Draft>
        
        var body: some View {
            NavigationView {
                List {
                    ForEach(drafts) { draft in
                        Button(action: { controller.maybeSelectDraft(draft) }) {
                            DraftRow(draft: draft)
                        }
                        .contextMenu {
                            Button(role: .destructive, action: { controller.deleteDraft(draft) }) {
                                Label("Delete Draft", systemImage: "trash")
                            }
                        }
                        .ifLet(controller.parent.config.userActivityForDraft(draft), modify: { view, activity in
                            view.onDrag { activity }
                        })
                    }
                    .onDelete { indices in
                        indices.map { drafts[$0] }.forEach(controller.deleteDraft)
                    }
                }
                .listStyle(.plain)
                .navigationTitle("Drafts")
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .cancellationAction) { cancelButton }
                }
            }
            .alertWithData("Different Reply", data: $controller.draftForDifferentReply) { draft in
                Button(role: .cancel, action: controller.cancelSelectingDraft) {
                    Text("Cancel")
                }
                Button(action: { controller.confirmSelectDraft(draft) }) {
                    Text("Restore Draft")
                }
            } message: { _ in
                Text("The selected draft is a reply to a different post, do you wish to use it?")
            }
            .onAppear {
                drafts.nsPredicate = NSPredicate(format: "accountID == %@ AND id != %@ AND lastModified != nil", controller.parent.mastodonController.accountInfo!.id, currentDraft.id as NSUUID)
            }
        }
        
        private var cancelButton: some View {
            Button(action: controller.closeDrafts) {
                Text("Cancel")
            }
        }
    }
}

private struct DraftRow: View {
    @ObservedObject var draft: Draft
    @EnvironmentObject private var controller: DraftsController
    
    var body: some View {
        HStack {
            VStack(alignment: .leading) {
                if draft.editedStatusID != nil {
                    // shouldn't happen unless the app crashed/was killed during an edit
                    Text("Edit")
                        .font(.body.bold())
                        .foregroundColor(.orange)
                }
                
                if draft.contentWarningEnabled {
                    Text(draft.contentWarning)
                        .font(.body.bold())
                        .foregroundColor(.secondary)
                }
                
                Text(draft.text)
                    .font(.body)
                
                HStack(spacing: 8) {
                    ForEach(draft.draftAttachments) { attachment in
                        ControllerView(controller: { AttachmentThumbnailController(attachment: attachment, parent: controller.parent) })
                            .aspectRatio(contentMode: .fit)
                            .clipShape(RoundedRectangle(cornerRadius: 5))
                            .frame(height: 50)
                    }
                }
            }
            
            Spacer()
            
            if let lastModified = draft.lastModified {
                Text(lastModified.formatted(.abbreviatedTimeAgo))
                    .font(.body)
                    .foregroundColor(.secondary)
            }
        }
    }
}

private extension View {
    @ViewBuilder
    func ifLet<T, V: View>(_ value: T?, modify: (Self, T) -> V) -> some View {
        if let value {
            modify(self, value)
        } else {
            self
        }
    }
}
