import Foundation
import SFSafeSymbols

enum FileTypeCategory: String, CaseIterable {
    case image
    case code
    case model
    case text
    case video
    case resource
    case audio
    case route

    var text: String {
        switch self {
        case .image: return "Images"
        case .code: return "Code"
        case .model: return "Models"
        case .text: return "Text"
        case .video: return "Videos"
        case .resource: return "Other"
        case .audio: return "Audio"
        case .route: return "Route"
        }
    }

    var symbol: SFSymbol {
        switch self {
        case .image: .photo
        case .code: .keyboard
        case .model: .cubeTransparent
        case .text: .textDocument
        case .video: .video
        case .resource: .zipperPage
        case .audio: .speakerWave2CircleFill
        case .route: .map
        }
    }
}

extension FileTypeCategory: Hashable {
    
}

extension FileTypeCategory: Identifiable {

    var id: String {
        rawValue
    }
}

enum FileType: String {

    // MARK: Images

    case jpg

    case png

    case avif

    case webp

    case gif

    case svg

    case tiff

    case ico

    // MARK: Code

    case html

    case cpp

    case swift

    case sh

    case js

    case css

    // MARK: Text

    case json

    case conf

    case yaml

    case txt

    case gpx

    // MARK: Model

    case stl

    case f3d

    case step

    case glb

    case f3z

    // MARK: Video

    case mp4

    case m4v

    case webm

    // MARK: Audio

    case mp3

    case aac

    case m4b

    case m4a

    // MARK: Other

    case noExtension

    case ttf

    case zip

    case cddx

    case pdf

    case key

    case psd

    // MARK: Route

    case route

    // MARK: Unknown

    case unknown

    init(fileExtension: String?) {
        guard let lower = fileExtension?.lowercased() else {
            self = .noExtension
            return
        }
        if lower == "jpeg" {
            self = .jpg
            return
        }
        guard let type = FileType(rawValue: lower) else {
            self = .unknown
            return
        }
        self = type
    }

    var category: FileTypeCategory {
        switch self {
        case .jpg, .png, .avif, .webp, .gif, .svg, .tiff, .ico:
            return .image
        case .mp4, .m4v, .webm:
            return .video
        case .mp3, .aac, .m4b, .m4a:
            return .audio
        case .json, .conf, .yaml, .txt, .gpx:
            return .text
        case .html, .cpp, .swift, .sh, .js, .css:
            return .code
        case .stl, .f3d, .step, .glb, .f3z:
            return .model
        case .zip, .cddx, .pdf, .key, .psd, .ttf:
            return .resource
        case .route:
            return .route
        case .noExtension, .unknown:
            return .resource
        }
    }

    var fileExtension: String? {
        switch self {
        case .noExtension, .unknown: return nil
        default:
            return rawValue
        }
    }

    var isImage: Bool {
        category == .image
    }

    var generatesImageVersions: Bool {
        switch self {
        case .jpg, .png, .avif, .webp, .tiff:
            return true
        default:
            return false
        }
    }

    var isVideo: Bool {
        category == .video
    }

    var isAudio: Bool {
        category == .audio
    }

    var isLikelyAssetType: Bool {
        switch self {
        case .js, .css, .ttf, .ico: true
        default: false
        }
    }

    var isTextFile: Bool {
        switch category {
        case .text, .code: return true
        default: break
        }
        switch self {
        case .css, .js: return true
        default: return false
        }
    }
}
