//  Common data/code that is used by any method
//

import UIKit

struct C
{

static var itinerary: Itinerary!

static var GCM_PROTO: String = "sojourn-13579"

static var WATCH_UUID: String = "8f737424-5a17-48c7-9b9e-b69c37714369"
enum WATCH_ACT: Int {
    case TITLE = 0
    case SEND
    case START
}

static var window: UIWindow?

static var json_url: URL? = nil

enum EV_TYPE: Int {
    case FLIGHT = 0
    case RIDE
    case RENTAL
    case TRAIN
    case LODGING
    case ACTIVITY
}
static var types: [ String ] = [
    "Flight", "Ride", "Rental", "Train", "Lodging", "Activity"
]

enum DATE_FMT: Int {
    case MDYYYY = 0
    case DMYYYY
    case YYYYMD
}
static var date_fmt: DATE_FMT = .MDYYYY
static var fmts: [ String ] = [ "M/d/yyyy", "d/M/yyyy", "yyyy/M/d" ]

static var lbl_flight: [String: String] = [
    "start":    "Depart",
    "end":      "Arrive",
    "to":       "Destination",
    "carrier":  "Airline",
    "ident":    "Flight",
    "gate":     "Gate",
    "seat":     "Seat",
    "address":  "",
    "phone":    "",
    "desc":     ""
]

static var lbl_ride: [String: String] = [
    "start":    "Depart",
    "end":      "Arrive",
    "to":       "Destination",
    "carrier":  "Service",
    "ident":    "License",
    "gate":     "",
    "seat":     "",
    "address":  "",
    "phone":    "",
    "desc":     ""
]

static var lbl_rental: [String: String] = [
    "start":    "Pickup",
    "end":      "Dropoff",
    "to":       "",
    "carrier":  "Company",
    "ident":    "",
    "gate":     "",
    "seat":     "",
    "address":  "",
    "phone":    "",
    "desc":     ""
]

static var lbl_train: [String: String] = [
    "start":    "Depart",
    "end":      "Arrive",
    "to":       "Destination",
    "carrier":  "Railway",
    "ident":    "Train",
    "gate":     "Platform",
    "seat":     "Seat",
    "address":  "",
    "phone":    "",
    "desc":     ""
]

static var lbl_lodging: [String: String] = [
    "start":    "Depart",
    "end":      "Arrive",
    "to":       "",
    "carrier":  "Company",
    "ident":    "",
    "gate":     "",
    "seat":     "Room",
    "address":  "Address",
    "phone":    "Phone",
    "desc":     ""
]

static var lbl_activity: [String: String] = [
    "start":    "Start",
    "end":      "End",
    "to":       "Destination",
    "carrier":  "",
    "ident":    "",
    "gate":     "",
    "seat":     "",
    "address":  "",
    "phone":    "",
    "desc":     "Description"
]

static func get_persist(_ key: String) -> Any?
{

    return UserDefaults.standard.string(forKey: key)
}

static func put_persist(_ key: String, val: Any?)
{

    UserDefaults.standard.set(val, forKey: key)
    return
}

static func rm_persist(_ key: String)
{
    UserDefaults.standard.removeObject(forKey: key)
    return
}

static func popup_sv(_ sender: PopupVC) -> UIStackView
{

    let scroll = UIScrollView()
    scroll.translatesAutoresizingMaskIntoConstraints = false
    sender.view.addSubview(scroll)
    NSLayoutConstraint.activate([
        scroll.topAnchor.constraint(equalTo: sender.TitleLbl.bottomAnchor, constant: 20),
        scroll.leadingAnchor.constraint(equalTo: sender.view.safeAreaLayoutGuide.leadingAnchor, constant: 10),
        scroll.trailingAnchor.constraint(equalTo: sender.view.safeAreaLayoutGuide.trailingAnchor, constant: -10),
        scroll.bottomAnchor.constraint(equalTo: sender.view.bottomAnchor)
    ])

    let stack = UIStackView()
    stack.axis = .vertical
    stack.alignment = .fill
    stack.distribution = .fill
    stack.spacing = 10
    stack.translatesAutoresizingMaskIntoConstraints = false
    scroll.addSubview(stack)
    NSLayoutConstraint.activate([
        stack.topAnchor.constraint(equalTo: scroll.topAnchor),
        stack.bottomAnchor.constraint(equalTo: scroll.bottomAnchor, constant: -20),
        stack.leadingAnchor.constraint(equalTo: scroll.leadingAnchor),
        stack.trailingAnchor.constraint(equalTo: scroll.trailingAnchor),
        stack.widthAnchor.constraint(equalTo: scroll.widthAnchor)
    ])
    return stack
}

static func alert(_ title: String, msg: String, cancel: Bool, vc: UIViewController, cb: @escaping (() -> ()) = {})
{

    let ac = UIAlertController(title: title, message: msg, preferredStyle: .alert)

    if (cancel) {
        ac.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
        }))
    }

    ac.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
        cb()
    }))

    ac.popoverPresentationController?.sourceView = vc.view

    vc.present(ac, animated: true, completion: nil)
}
static func alert(_ title: String, msg: String, vc: UIViewController, cb: @escaping (() -> ()) = {})
{

    alert(title, msg: msg, cancel: true, vc: vc, cb: cb)
}
static func alert(_ title: String, msg: String, vc: UIViewController)
{

    alert(title, msg: msg, cancel: false, vc: vc) { () in
    }
}
static func alert(_ title: String, msg: String)
{

    if let win = UIApplication.shared.connectedScenes.first as? UIWindowScene,
       let scene = win.windows.first(where: { $0.isKeyWindow })?.rootViewController {
        
        // Find the currently visible controller (it might be a child or a modal)
        var vc = scene
        while let nvc = vc.presentedViewController {
            vc = nvc
        }
        
        alert(title, msg: msg, vc: vc)
    }
}

static func app_restart()
{

Log.l("app_restart()")
    let sb = UIStoryboard(name: "Main", bundle: nil)
    let vc = sb.instantiateViewController(withIdentifier: "TripVC")
    let nav = UINavigationController(rootViewController: vc)

    window?.rootViewController = nav
}

static func type2i(_ type: String) -> EV_TYPE
{
    for i in 0..<types.count {
        if (type == types[i]) {
            return EV_TYPE(rawValue: i) ?? .FLIGHT }
    }
    return .FLIGHT
}

static func str2epoch(_ str: String) -> Int
{

    let df = DateFormatter()
    df.dateFormat = fmts[date_fmt.rawValue]
    df.timeZone = TimeZone(secondsFromGMT: 0)
    if let date = df.date(from: str) {
        return Int(date.timeIntervalSince1970) }
Log.l("st2epoch:bad date string - \(str)")
    return 0
}

static func epoch2str(_ epoch: Int, fmt: DATE_FMT?) -> String
{

    let df = DateFormatter()
    df.dateFormat = fmts[date_fmt.rawValue]
    df.timeZone = TimeZone(secondsFromGMT: 0)
    return df.string(from: Date(timeIntervalSince1970: Double(epoch)))
}

static func epoch2str(_ epoch: Int) -> String
{

    return epoch2str(epoch, fmt: date_fmt)
}

static func dow(_ epoch: Int) -> String
{

    let df = DateFormatter()
    df.dateFormat = "E " + fmts[date_fmt.rawValue]
    df.timeZone = TimeZone(secondsFromGMT: 0)
    return df.string(from: Date(timeIntervalSince1970: Double(epoch)))
}

static func str2hm(_ str: String) -> Int
{
    var pm: Int = 0
    var min: String = "0"

    if str.isEmpty {
        return -1 }

    let time = str.replacingOccurrences(of: "\\s+", with: "", options: .regularExpression)
    let suf = time.replacingOccurrences(of: "[0-9:]+", with: "", options: .regularExpression)
    if suf.hasPrefix("p") ||
       suf.hasPrefix("P") {
        pm = 12 * 3600 }
    var digs = time.replacingOccurrences(of: "[^0-9:]+", with: "", options: .regularExpression)
    let parts = digs.split(separator: ":")
    if parts.count > 1 {
        digs = String(parts[0])
        min = String(parts[1])
    }
    guard var hr = Int(digs),
          let mn = Int(min) else {
Log.l("bad time:\(digs):\(min),\(pm)")
        return -1 }
    if (hr == 12 && pm == 0) {
        hr = 0 }
    //let r: Int = (hr * 3600) + (Int(min) * 60) + pm
    var r = hr * 3600
    r += mn * 60
    r += pm
//Log.l("\(str):\(String(hr)),\(String(mn)),\(String(pm)) = \(r)")
    return r
}

static func hm2str(_ tm: Int) -> String
{
    var pm = "AM"

    if tm < 0 {
        return "" }

    var hr = tm / 3600
    let mn = (tm - (hr * 3600)) / 60
    if hr >= 12 {
        hr -= 12
        pm = "PM"
    }
    let mm = (mn < 10) ? "0\(mn)" : "\(mn)"
    return "\(hr):\(mm)\(pm)"
}

static func today() -> String
{

    return epoch2str(Int(Date().timeIntervalSince1970))
}

static func get_trip() -> String?
{

    return get_persist("Trip_JSON") as? String
}

static func put_trip(_ val: String)
{

//Log.l("put_trip:\(val)")
    C.put_persist("Trip_JSON", val: val)
}

static func put_trip()
{

    put_trip(Json.json2str(itinerary.marshall())!)
}

}
