//Licensed to the Apache Software Foundation (ASF) under one
//or more contributor license agreements.  See the NOTICE file
//distributed with this work for additional information
//    regarding copyright ownership.  The ASF licenses this file
//to you under the Apache License, Version 2.0 (the
//"License"); you may not use this file except in compliance
//with the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing,
//software distributed under the License is distributed on an
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//KIND, either express or implied.  See the License for the
//specific language governing permissions and limitations
//under the License.

import Foundation
import UIKit
import DeviceKit

final class ATSDevice: Encodable {
    
    enum Button: String, CaseIterable {
        case home
        case lock
        case volumeDown
        case volumeUp
    }
    
    enum Property: String, CaseIterable {
        // case airplaneModeEnabled
        // case wifiEnabled
        case cellularDataEnabled
        case bluetoothEnabled
        case orientation
        // case brightness
        // case volume
    }
    
    static let current = ATSDevice()
    
    let os = "ios"
    
    let driverVersion: String
    let driverBuildNumber: String
    
    let name: String
    let modelName: String
    let uuid: String
    
    let systemVersion: String
    let systemBuildNumber: String
    let systemCountry = NSLocale.current.regionCode ?? ""
    
    let description: String
    
    var deviceWidth: CGFloat = 0
    var deviceHeight: CGFloat = 0
    var channelWidth: CGFloat = 0
    var channelHeight: CGFloat = 0
    let deviceScale = UIScreen.main.scale
    
    let isSimulator: Bool
    let isPhone: Bool
    
    let screenCapturePort = Int.random(in: 32000..<64000)
    
    let systemProperties = Property.allCases.map { $0.rawValue }
    let systemButtons = Button.allCases.map { $0.rawValue }
    
    private(set) var applications: [Application] = []
    
    private init() {
        let bundleInfo = Bundle.main.infoDictionary
        self.driverBuildNumber = bundleInfo?["CFBundleVersion"] as? String ?? ""
        self.driverVersion = bundleInfo?["CFBundleShortVersionString"] as? String ?? ""
        
        let uiDevice = UIDevice.current
        self.name = uiDevice.name
        self.uuid = uiDevice.identifierForVendor!.uuidString
        self.systemVersion = uiDevice.systemVersion
        
        self.systemBuildNumber = ATSDevice.fetchSystemBuildNumber()

    
        let device = Device.current
        let modelName = Device.current.description
        self.modelName = modelName
        self.description = modelName + " - " + systemVersion
        self.isSimulator = device.isSimulator
        self.isPhone = device.isPhone
    }
    
    func setApplications(_ applications: [String]) {
        self.applications = applications.map { Application(label: "CFBundleName", packageName: String($0), version: "", icon: DefaultAppIcon()) }
    }
    
    private static func fetchSystemBuildNumber() -> String {
        var systemVersionString = ProcessInfo.init().operatingSystemVersionString

        guard let range = systemVersionString.range(of: "Build ") else {
            return ""
        }
        
        systemVersionString.removeSubrange(systemVersionString.startIndex..<range.upperBound)
        systemVersionString.removeLast()

        return systemVersionString
    }
    
    func setDeviceSize(size: CGRect) {
        self.deviceWidth = size.width
        self.deviceHeight = size.height
        self.channelWidth = size.width * deviceScale
        self.channelHeight = size.height * deviceScale
    }
}
