//
//  PollController.swift
//  ComposeUI
//
//  Created by Shadowfacts on 3/25/23.
//

import SwiftUI
import TuskerComponents

class PollController: ViewController {
    
    unowned let parent: ComposeController
    var draft: Draft { parent.draft }
    let poll: Poll
    
    @Published var duration: Duration
    
    init(parent: ComposeController, poll: Poll) {
        self.parent = parent
        self.poll = poll
        self.duration = .fromTimeInterval(poll.duration) ?? .oneDay
    }
    
    var view: some View {
        PollView()
            .environmentObject(poll)
    }
    
    private func removePoll() {
        withAnimation {
            draft.poll = nil
        }
    }
    
    private func moveOptions(indices: IndexSet, newIndex: Int) {
        poll.options.moveObjects(at: indices, to: newIndex)
    }
    
    private func removeOption(_ option: PollOption) {
        poll.options.remove(option)
    }
    
    private var canAddOption: Bool {
        if let max = parent.mastodonController.instanceFeatures.maxPollOptionsCount {
            return poll.options.count < max
        } else {
            return true
        }
    }
    
    private func addOption() {
        let option = PollOption(context: DraftsPersistentContainer.shared.viewContext)
        option.poll = poll
        poll.options.add(option)
    }
    
    struct PollView: View {
        @EnvironmentObject private var controller: PollController
        @EnvironmentObject private var poll: Poll
        @Environment(\.colorScheme) private var colorScheme
        
        var body: some View {
            VStack {
                HStack {
                    Text("Poll")
                        .font(.headline)
                    
                    Spacer()
                    
                    Button(action: controller.removePoll) {
                        Image(systemName: "xmark")
                            .imageScale(.small)
                            .padding(4)
                    }
                    .accessibilityLabel("Remove poll")
                    .buttonStyle(.plain)
                    .accentColor(buttonForegroundColor)
                    .background(Circle().foregroundColor(buttonBackgroundColor))
                    .hoverEffect()
                }
                
                List {
                    ForEach($poll.pollOptions) { $option in
                        PollOptionView(option: option, remove: { controller.removeOption(option) })
                            .frame(height: 36)
                            .listRowInsets(EdgeInsets(top: 4, leading: 0, bottom: 4, trailing: 0))
                            .listRowSeparator(.hidden)
                            .listRowBackground(Color.clear)
                    }
                    .onMove(perform: controller.moveOptions)
                }
                .listStyle(.plain)
                .scrollDisabledIfAvailable(true)
                .frame(height: 44 * CGFloat(poll.options.count))
                
                Button(action: controller.addOption) {
                    Label {
                        Text("Add Option")
                    } icon: {
                        Image(systemName: "plus")
                            .foregroundColor(.accentColor)
                    }
                }
                .buttonStyle(.borderless)
                .disabled(!controller.canAddOption)
                
                HStack {
                    MenuPicker(selection: $poll.multiple, options: [
                        .init(value: true, title: "Allow multiple"),
                        .init(value: false, title: "Single choice"),
                    ])
                    .frame(maxWidth: .infinity)
                    
                    MenuPicker(selection: $controller.duration, options: Duration.allCases.map {
                        .init(value: $0, title: Duration.formatter.string(from: $0.timeInterval)!)
                    })
                    .frame(maxWidth: .infinity)
                }
            }
            .padding(8)
            .background(
                RoundedRectangle(cornerRadius: 10, style: .continuous)
                    .foregroundColor(backgroundColor)
            )
            .onChange(of: controller.duration) { newValue in
                poll.duration = newValue.timeInterval
            }
        }
        
        private var backgroundColor: Color {
            // in light mode, .secondarySystemBackground has a blue-ish hue, which we don't want
            colorScheme == .dark ? controller.parent.config.fillColor : Color(white: 0.95)
        }
        
        private var buttonForegroundColor: Color {
            Color(uiColor: .label)
        }
        
        private var buttonBackgroundColor: Color {
            Color(white: colorScheme == .dark ? 0.1 : 0.8)
        }
    }
}

extension PollController {
    enum Duration: Hashable, Equatable, CaseIterable {
        case fiveMinutes, thirtyMinutes, oneHour, sixHours, oneDay, threeDays, sevenDays
        
        static let formatter: DateComponentsFormatter = {
            let f = DateComponentsFormatter()
            f.maximumUnitCount = 1
            f.unitsStyle = .full
            f.allowedUnits = [.weekOfMonth, .day, .hour, .minute]
            return f
        }()
        
        static func fromTimeInterval(_ ti: TimeInterval) -> Duration? {
            for it in allCases where it.timeInterval == ti {
                return it
            }
            return nil
        }
        
        var timeInterval: TimeInterval {
            switch self {
            case .fiveMinutes:
                return 5 * 60
            case .thirtyMinutes:
                return 30 * 60
            case .oneHour:
                return 60 * 60
            case .sixHours:
                return 6 * 60 * 60
            case .oneDay:
                return 24 * 60 * 60
            case .threeDays:
                return 3 * 24 * 60 * 60
            case .sevenDays:
                return 7 * 24 * 60 * 60
            }
        }
    }
}
