//
//  LoginView.swift
//  forShip
//
//  Created by Mamoru Sugita on 2023/10/13.
//

import SwiftUI

enum LoginViewMode: String{
    ///QRを読み込むor ID/PW入力か選択する画面
    case SelectType
    /// ID/PW入力
    case InputIdPassword
    /// ユーザー名入力
    case InputUserName
}

enum AlertType: String {
    case loginFailure
    case Expired
    case gpsPermission
}

class LoginViewParam: ObservableObject{
    @Published var shipId: String = ""
    @Published var password: String = ""
    @Published var userName: String = ""
}

struct LoginView: View {
    @Binding var isLogin: Bool
    @State var isQrRead: Bool = false
    @State var viewMode: LoginViewMode = .SelectType
    @State var isProgressView = false
    @State var isAlert = false
    @State var alertType: AlertType = .loginFailure
    @ObservedObject var scannerViewModel = ScannerViewModel()
    @State var loginViewParam = LoginViewParam()
    @State var timer :Timer?
    @StateObject var locationViewModel = LocationViewModel()
    let sessionLogin = SessionLogin()

    var body: some View {
        ZStack{
            Triangle()
                .fill(ColorSet.LoginBk03.color)
                .ignoresSafeArea()
            VStack{
                //ロゴ
                VStack(spacing: 20){
                    Image("logo_signin")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 135, height: 66.85)

                    Image("h1_signin")
                        .frame(width: 250, height: 21.94)
                }
                .padding(.top, 64)

                Spacer()

                if !isProgressView {
                    switch viewMode{
                    case .SelectType:
                        LoginTypeSelectView(isQrRead: $scannerViewModel.isShowing, viewMode: $viewMode)
                    case .InputIdPassword:
                        InputIdPassWordView(viewMode: $viewMode, param: $loginViewParam)
                    case .InputUserName:
                        InputUserNameView(isLogin: $isLogin, param: $loginViewParam, viewMode: $viewMode, isProgressView: $isProgressView, isAlert: $isAlert, alertType: $alertType)
                    }
                } else {
                    Text("Login Check").padding()
                    ProgressView()
                }

                Spacer()

                VStack(spacing: 40){
                    VStack(spacing: 30) {
                        if !isProgressView {
                            Link("Site policy", destination: URL(string: HttpRequestType.SitePolicy.rawValue)!)
                            Link("Cookie policy", destination: URL(string: HttpRequestType.CookiePolicy.rawValue)!)
                            Link("Privacy policy", destination: URL(string: HttpRequestType.PrivacyPolicy.rawValue)!)
                        } else {
                            EmptyView()
                        }
                    }
                    .font(FontStyle.SupplementText.font)
                    .foregroundColor(ColorSet.Body.color)

                    Text("Ver. \(Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String)")
                        .font(FontStyle.VersionText.font)
                        .foregroundColor(ColorSet.BodyDescriptiion.color)
                }
                .padding(.bottom, 30)
                .alert(isPresented: $isAlert) {
                    switch alertType {
                    case .loginFailure:
                        return Alert(title: Text("error"),
                                     message: Text("Login failure."),
                                     dismissButton: .default(Text("OK"), action: {viewMode = .SelectType})
                        )
                    case .Expired:
                        return Alert(title: Text("error"),
                                     message: Text("Expired."),
                                     dismissButton: .default(Text("OK"), action: {viewMode = .SelectType})
                        )
                    case .gpsPermission:
                        return Alert(title: Text("location"),
                                     message: Text("Allow use of location information."),
                                     dismissButton: .default(Text("Next"), action: {locationViewModel.requestPermission()})
                        )
                    }
                }
            }
        }
        .background(ColorSet.BackgroundPrimary.color)
        .fullScreenCover(isPresented: $scannerViewModel.isShowing, onDismiss: {LoginCheckQR()}, content: {
            QRReadView(viewMode: .constant(.SelectType), viewModel: scannerViewModel)
        })
        .onAppear() {
            LoginCheck()
            gpsCheck()
        }
        .preferredColorScheme(.dark)
    }

    func LoginCheckQR() -> () {
        loginViewParam.shipId = Preferences.ShipId
        loginViewParam.password = Preferences.ShipPassword
        viewMode = .InputUserName
    }

    func LoginCheck() -> () {
        let lastUnixTime = Preferences.lastLoginDate_Int64 ?? 0
        let lastDate = DateTextLib.UnixTime2Date(lastUnixTime)
        let interval = Date.now.timeIntervalSince(lastDate)

        if interval < 2592000 {
            if Preferences.ShipId != "" && Preferences.ShipPassword != "" && Preferences.UserName != ""{
                isProgressView = true
                let login = ReqLogin(Id: Preferences.ShipId, Password: Preferences.ShipPassword)
                sessionLogin.RequestLogin(login, completion: responseLogin)
            }
        }
    }

    func gpsCheck() -> () {
        switch locationViewModel.authorizationStatus {
        case .notDetermined:
            isAlert = true
            alertType = .gpsPermission
        case .restricted:
            ErrorView(errorText: "位置情報の使用が制限されています。")
        case .denied:
            ErrorView(errorText: "位置情報を使用できません。")
        case .authorizedAlways, .authorizedWhenInUse:
            print(debug: "called")
        default:
            Text("Unexpected status")
        }
    }

    func responseLogin(result: Result<Data, APIError>) {
        print(debug: "calld")
        switch result {
        case .success(let resultData):
            let serverSession = ServerSession()
            let resjson = serverSession.fromJSON(resultData: resultData, resltType: ResLogin.self)
            if let res = resjson {
                SharingData.my.id = res.id
                SharingData.my.shipId = res.shipId
                SharingData.my.shipName = res.shipName
                SharingData.my.imo = res.imo
                SharingData.my.mmsi = res.mmsi
            }

            Preferences.lastLoginDate_Int64 = DateTextLib.Date2UnixTime(date: Date())
            isLogin = true

            timer = Timer.scheduledTimer(withTimeInterval: 60.0, repeats: true) { _ in
                print(debug: "called timer")
                let eca = EcaTask()
                eca.start()

                let message = GetMessage()
                message.start()

                let route = MonitoringRoute()
                route.start()
            }
            timer?.fire()

        case .failure(let errorCode):
            print(debug: errorCode)
            isLogin = false
            isAlert = true
            alertType = .loginFailure
            break
        }
        isProgressView = false
    }
}

fileprivate struct Triangle: Shape{
    func path(in rect: CGRect) -> Path {
        Path{ path in
            let screen = UIScreen.main.bounds
            path.move(to: CGPoint(x: 63, y: screen.maxY))
            path.addLine(to: CGPoint(x: screen.maxX, y: 165))
            path.addLine(to: CGPoint(x: screen.maxX, y: screen.maxY))
            path.closeSubpath()
        }
    }
}

#Preview {
    LoginView(isLogin: .constant(false))
}
