//
//  LKFConvert.swift
//  lkfc
//
//  Created by Alexander Holzer on 12.06.21.
//  Copyright © 2021 Alexander Holzer. All rights reserved.
//

import Foundation
@_implementationOnly import LibLKF

public extension String {
    static func utf8String (cString: UnsafeMutablePointer<CChar>) -> String {
        if let s = String(cString: cString,encoding: .utf8) {
            return s
        }
        return String(cString: cString)
    }
}

public extension Data {
    func toString (encodings: [String.Encoding]) -> (String,String.Encoding)? {
        for e in encodings {
            if let s = String(data: self, encoding: e) {
                return (s,e)
            }
        }
        return nil
    }
    
    func toString (encoding: String.Encoding) -> String? {
        if let s = String(data: self, encoding: encoding) {
            return s
        }
        return nil
    }
}

public class LKFConvert {
    public static func toDate (string8: String) -> Date? {
        guard string8.count == 8 && string8.first != " " else {
            return nil
        }
        
        let indexEndYear = string8.index (string8.startIndex, offsetBy:4)
        let indexEndMonth = string8.index (string8.startIndex, offsetBy:6)
        let indexEndDay = string8.index(string8.startIndex, offsetBy:8)

        var dateComponents = DateComponents()

        dateComponents.year = Int(string8[..<indexEndYear])
        dateComponents.month = Int(string8[indexEndYear..<indexEndMonth])
        dateComponents.day = Int(string8[indexEndMonth..<indexEndDay])

        return Calendar.current.date(from: dateComponents)
    }
    
    public static var shortDateFormatter : DateFormatter = {
        let d = DateFormatter ()
        d.dateStyle = .short
        return d
    }()

    public static var mediumDateFormatter : DateFormatter = {
        let d = DateFormatter ()
        d.dateStyle = .medium
        return d
    }()

    public static var dayMonthDateFormatter: DateFormatter = {
        let d = DateFormatter ()
        d.setLocalizedDateFormatFromTemplate("dd.MM")
        return d

    }()

    public static var dateTimeFormatter: DateFormatter = {
        let d = DateFormatter()
        d.dateFormat = "yyyy-MM-dd HH:mm:ss"
        return d

    }()
    
    public static var numberFormatterNoDec : NumberFormatter = {
       let n = NumberFormatter()
       n.locale = Locale.current
       n.maximumFractionDigits = 0
       n.groupingSize = 3
       n.usesGroupingSeparator = true
       return n
    }()

    public static var numberFormatter2Dec : NumberFormatter = {
       let n = NumberFormatter()
        n.locale = Locale.current
        n.minimumFractionDigits = 2
        n.groupingSize = 3
        n.maximumFractionDigits = 2
       return n
    }()
    
    public static func toShortString (date: Date) -> String {
        return LKFConvert.shortDateFormatter.string(from: date)
    }
    
    public static func toShortString (optionalDate: Date?) -> String {
        if let date = optionalDate {
            return LKFConvert.shortDateFormatter.string(from: date)
        }
        return ""
    }

    public static func toMediumString (optionalDate: Date?) -> String {
        if let date = optionalDate {
            return LKFConvert.mediumDateFormatter.string(from: date)
        }
        return ""
    }

    public static func toMediumString (date: Date) -> String {
        return LKFConvert.mediumDateFormatter.string(from: date)
    }

    
    public static func dateTimeString (date: Date?, time: LKFTime? = nil) -> String? {
        if let d = date {
            
            if let t = time {
                return "\(toShortString(date: d)), \(t.string)"
            }
            else {
                return toShortString(date: d)
            }
        }
        return nil
    }
    
    public static func toDate (from intValue: Int) -> String {
        let lineBuffer = UnsafeMutablePointer<CChar>.allocate(capacity:32)
        
        defer {
            lineBuffer.deallocate()
        }
        LibLKF.lkf_LongToDat(intValue, lineBuffer)
        return String (cString: lineBuffer)
    }

    public static func toDate8 (from intValue: Int) -> String {
        let lineBuffer = UnsafeMutablePointer<CChar>.allocate(capacity:32)
        
        defer {
            lineBuffer.deallocate()
        }
        LibLKF.lkf_LongToDat8 (intValue, lineBuffer)
        return String (cString: lineBuffer)
    }

    public static func toInt (from dateString: String) -> Int {
        return LibLKF.lkf_DatToLong(dateString.cString(using: .utf8))
    }
}

public class LKFTime {
    public let hour: Int
    public let minute: Int
    
    public init? (_ s: String) {
        
        if s.count < 4 {
            return nil
        }
        
        var minuteIndex = s.index(s.startIndex,offsetBy: 2)
        
        guard let h = Int(s[s.startIndex..<minuteIndex]), h >= 0 && h < 24 else {
            return nil
        }
        hour = h

        if ":.".firstIndex(of: s[minuteIndex]) != nil {
            minuteIndex = s.index(minuteIndex, offsetBy: 1)
            if s.count < 5 {
                return nil
            }
        }

        guard let m = Int(s[minuteIndex..<s.index(minuteIndex, offsetBy: 2)]), m >= 0 && m < 60 else {
            return nil
        }
        minute = m
    }
    
    public var string : String {
        return String(format: "%02d:%02d", hour, minute)
    }
}
