//
//  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 QrFailure
    case ClientError
    case Expired
}

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

let TimerInterval = 60.0

struct LoginView: View {
    @ObservedObject var scannerViewModel = ScannerViewModel()
    @EnvironmentObject var locationViewModel: LocationViewModel
    @EnvironmentObject var selectedTabModel: SelectedTabModel
    @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
    @State var loginViewParam = LoginViewParam()
    @State var timer :Timer?

    let sessionLogin = SessionLogin()

    var body: some View {
        NavigationView {
            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("Information", destination: URL(string: HttpRequestType.SitePolicy.rawValue)!)
                                Link("Contact Us", destination: URL(string: HttpRequestType.ContactPage.rawValue)!)
                                NavigationLink {
                                    AboutAppView()
                                } label: {
                                    Text("About This App")
                                }
                            } 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("Ship ID or Password is incorrect."),
                                         dismissButton: .default(Text("OK"), action: {viewMode = .SelectType})
                            )
                        case .QrFailure:
                            return Alert(title: Text("Error"),
                                         message: Text("QR code is incorrect."),
                                         dismissButton: .default(Text("OK"), action: {viewMode = .SelectType})
                            )
                        case .ClientError:
                            return Alert(title: Text("Error"),
                                         message: Text("Not connected to network."),
                                         dismissButton: .default(Text("OK"), action: {viewMode = .SelectType})
                            )
                        case .Expired:
                            return Alert(title: Text("Error"),
                                         message: Text("Expired."),
                                         dismissButton: .default(Text("OK"), action: {viewMode = .SelectType})
                            )
                        }
                    }
                }
            }
            .background(ColorSet.BackgroundPrimary.color)
            .fullScreenCover(isPresented: $scannerViewModel.isShowing, onDismiss: {LoginCheckQR()}, content: {
                QRReadView(viewMode: .constant(.SelectType), viewModel: scannerViewModel)
            })

            .onAppear(perform: {
                LoginCheck()
                let manual = GetManualUrl()
                manual.start()
                selectedTabModel.isLocationAlert = locationViewModel.requestPermission()
            })
            .preferredColorScheme(.dark)
        }
    }

    func LoginCheckQR() -> () {
        isProgressView = true
        loginViewParam.shipId = Preferences.Id
        loginViewParam.password = Preferences.Password
        loginViewParam.deviceid = Preferences.DeviceId
        loginViewParam.userName = Preferences.UserName

        let login = ReqLogin(Id: Preferences.Id, Password: Preferences.Password, DeviceId: Preferences.DeviceId, UserName: Preferences.UserName)
        sessionLogin.RequestLogin(login, completion: responseQrLogin)
    }

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

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

    func responseQrLogin(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.shipName = res.shipName
                SharingData.my.imo = res.imo
                SharingData.my.mmsi = res.mmsi

                Preferences.shipId = res.shipId

                let notificationTags = NotificationTags()
                notificationTags.addTags()
            }

            Preferences.lastLoginDate_Int64 = DateTextLib.Date2UnixTime(date: Date())
            viewMode = .InputUserName

            //            let ecaArea = EcaArea()
            //            ecaArea.start()

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

                let message = GetMessage()
                message.start()

                let route = MonitoringRoute()
                route.start()

                let ecaList = GetEcaList()
                ecaList.start()

                let pushHistory = GetPushHistory()
                pushHistory.start()
            }
            timer?.fire()

        case .failure(let errorCode):
            print(debug: errorCode)
            switch errorCode {
            case .clientError:
                alertType = .ClientError
            case .serverError:
                alertType = .QrFailure
            default:
                alertType = .QrFailure
            }
            isLogin = false
            isAlert = true
            break
        }
        isProgressView = false
    }

    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.shipName = res.shipName
                SharingData.my.imo = res.imo
                SharingData.my.mmsi = res.mmsi

                Preferences.shipId = res.shipId

                let notificationTags = NotificationTags()
                notificationTags.addTags()
            }

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

            //            let ecaArea = EcaArea()
            //            ecaArea.start()

            let eca = EcaTask()
            eca.start()

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

                let message = GetMessage()
                message.start()

                let route = MonitoringRoute()
                route.start()

                let ecaList = GetEcaList()
                ecaList.start()

                let pushHistory = GetPushHistory()
                pushHistory.start()
            }
            timer?.fire()

        case .failure(let errorCode):
            print(debug: errorCode)
            switch errorCode {
            case .clientError:
                alertType = .ClientError
            case .serverError:
                alertType = .loginFailure
            default:
                alertType = .loginFailure
            }
            isLogin = false
            isAlert = true
            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))
        .environmentObject(SelectedTabModel())
}
