//
//  TagListView.swift
//  ColorfulWallpaper
//
//  Created by nkl on 2024/9/11.
//

import Foundation
import KLExtension
import SwiftUI
let kStore_History_Key = "Historys"

public struct HistoryModel: Codable {
    var keyword: String
    var id: String
    var date: Date
}

class HistoryViewModel: ObservableObject {
    @Published var historys: [HistoryModel] = []

    init() {
        requestData()
    }

    func requestData() {
        let storage = CodableStorage()
        do {
            let historys: [HistoryModel] = try storage.fetch(for: kStore_History_Key)
            let result: [HistoryModel] = Array(historys.sorted(by: { $0.date > $1.date })
                .prefix(20))
            self.historys = result
        } catch {
            historys = []
        }
    }

    func deleteHistory(id: String) {
        let storage = CodableStorage()
        do {
            var historys: [HistoryModel] = try storage.fetch(for: kStore_History_Key)
            historys.removeAll {
                $0.id == id
            }
            try storage.save(historys, for: kStore_History_Key)
            self.historys = historys
        } catch {
            historys = []
        }
    }

    func deleteAllHistorys() {
        let storage = CodableStorage()
        do {
            let tmp: [HistoryModel] = []
            try storage.save(tmp, for: kStore_History_Key)
            historys = []
        } catch {
            historys = []
        }
    }
}

struct TagListView: View {
    var selectedHistoryTag: (HistoryModel) -> Void = { _ in }

    @ObservedObject var history: HistoryViewModel = .init()

    @State var isEditing: Bool = false

    var body: some View {
        VStack {
            if !history.historys.isEmpty {
                HStack {
                    Text("History".localized())
                        .foregroundColor(.white)
                        .font(.system(size: 16).bold())
                    Spacer()
                    HStack {
                        if isEditing {
                            HStack {
                                Text("Delete all".localized())
                                    .font(.system(size: 12))
                                    .foregroundColor(.white.opacity(0.6))
                                    .onTapGesture {
                                        history.deleteAllHistorys()
                                    }

                                Rectangle().frame(width: 1, height: 12)
                                    .foregroundColor(Color.white.opacity(0.6))

                                Text("Cancel".localized())
                                    .font(.system(size: 12))
                                    .foregroundColor(.red)
                                    .onTapGesture {
                                        isEditing = false
                                    }
                            }
                        } else {
                            Image("ic_history_clear")
                                .onTapGesture {
                                    isEditing = true
                                }
                        }
                    }
                }
                .padding(.horizontal, 16)
                .padding(.top, 30)
            }
            GeometryReader { geometry in
                TagLayoutView(
                    history.historys,
                    tagFont: UIFont.systemFont(ofSize: 12),
                    padding: 24,
                    parentWidth: geometry.size.width) { tag in
                        ZStack(alignment: .topTrailing) {
                            Text(tag.keyword)
                                .font(.system(size: 12))
                                .fixedSize()
                                .padding(EdgeInsets(top: 8, leading: 16, bottom: 8, trailing: 16))
                                .foregroundColor(Color.white)
                                .background(Color.white.opacity(0.1))
                                .clipShape(.capsule)
                            if isEditing {
                                Image("ic-close")
                                    .resizable()
                                    .frame(width: 8, height: 8)
                                    .padding(.trailing, 8)
                                    .padding(.top, 8)

                            }
                        }
                        .onTapGesture {
                            if isEditing {
                                history.deleteHistory(id: tag.id)
                            } else {
                                selectedHistoryTag(tag)
                            }
                        }
                    }.padding(.horizontal, 16)
            }
        }.onAppear(perform: {
            history.requestData()
        })
    }
}

#Preview(body: {
    TagListView()
})

@available(iOS 13.0, *)
public struct TagLayoutView<Content>: View where Content: View {
    private let tags: [HistoryModel]
    private var tagFont: UIFont
    private let padding: CGFloat
    private let parentWidth: CGFloat
    private let content: (HistoryModel) -> Content
    private var elementsCountByRow: [Int] = []

    public init(_ tags: [HistoryModel],
                tagFont: UIFont,
                padding: CGFloat,
                parentWidth: CGFloat,
                content: @escaping (HistoryModel) -> Content) {
        self.tags = tags
        self.tagFont = tagFont
        self.padding = padding
        self.parentWidth = parentWidth
        self.content = content
        elementsCountByRow = getElementsCountByRow(self.parentWidth)
    }

    private func getElementsCountByRow(_ rowSize: CGFloat) -> [Int] {
        let tagWidths = tags.map { $0.keyword.widthOfString(usingFont: self.tagFont) }

        var currentRowTotalWidth: CGFloat = 0.0
        var currentRowElementsCount: Int = 0
        var result: [Int] = []

        for tagWidth in tagWidths {
            let fixedTagWidth = tagWidth + (2 * padding)
            if currentRowTotalWidth + fixedTagWidth <= rowSize {
                currentRowTotalWidth += fixedTagWidth
                currentRowElementsCount += 1
                guard result.count != 0 else { result.append(1); continue }
                result[result.count - 1] = currentRowElementsCount
            } else {
                currentRowTotalWidth = fixedTagWidth
                currentRowElementsCount = 1
                result.append(1)
            }
        }
        return result
    }

    private func getTag(elementsCountByRow: [Int], rowIndex: Int, elementIndex: Int) -> HistoryModel {
        let sumOfPreviousRows = elementsCountByRow.enumerated().reduce(0) { total, next in
            if next.offset < rowIndex {
                return total + next.element
            } else {
                return total
            }
        }
        let orderedTagsIndex = sumOfPreviousRows + elementIndex
        guard tags.count > orderedTagsIndex else { return .init(keyword: "", id: "", date: Date()) }
        return tags[orderedTagsIndex]
    }

    public var body: some View {
        VStack(alignment: .leading, spacing: 0) {
            ForEach(0 ..< self.elementsCountByRow.count, id: \.self) { rowIndex in
                HStack {
                    ForEach(0 ..< self.elementsCountByRow[rowIndex], id: \.self) { elementIndex in
                        self.content(self.getTag(elementsCountByRow: self.elementsCountByRow, rowIndex: rowIndex, elementIndex: elementIndex))
                    }
                    Spacer()
                }.padding(.vertical, 4)
            }
        }
    }
}

extension String {
    func widthOfString(usingFont font: UIFont) -> CGFloat {
        let fontAttributes = [NSAttributedString.Key.font: font]
        let size = self.size(withAttributes: fontAttributes)
        return size.width
    }
}
