//
//  NewChatButton.swift
//  SimpleX
//
//  Created by Evgeny Poberezkin on 31/01/2022.
//  Copyright © 2022 SimpleX Chat. All rights reserved.
//

import SwiftUI
import SimpleXChat

enum NewChatAction: Identifiable {
    case createLink(link: String)
    case connectViaLink
    case createGroup

    var id: String {
        switch self {
        case let .createLink(link): return "createLink \(link)"
        case .connectViaLink: return "connectViaLink"
        case .createGroup: return "createGroup"
        }
    }
}

struct NewChatButton: View {
    @Binding var showAddChat: Bool
    @State private var actionSheet: NewChatAction?

    var body: some View {
        Button { showAddChat = true } label: {
            Image(systemName: "square.and.pencil")
                .resizable()
                .scaledToFit()
                .frame(width: 24, height: 24)
        }
        .confirmationDialog("Start a new chat", isPresented: $showAddChat, titleVisibility: .visible) {
            Button("Share one-time invitation link") { addContactAction() }
            Button("Connect via link / QR code") { actionSheet = .connectViaLink }
            Button("Create secret group") { actionSheet = .createGroup }
        }
        .sheet(item: $actionSheet) { sheet in
            switch sheet {
            case let .createLink(link):
                CreateLinkView(selection: .oneTime, connReqInvitation: link)
            case .connectViaLink: ConnectViaLinkView()
            case .createGroup: AddGroupView()
            }
        }
    }

    func addContactAction() {
        Task {
            if let connReq = await apiAddContact() {
                actionSheet = .createLink(link: connReq)
            }
        }
    }
}

enum ConnReqType: Equatable {
    case contact
    case invitation
}

func connectViaLink(_ connectionLink: String, _ dismiss: DismissAction? = nil) {
    Task {
        if let connReqType = await apiConnect(connReq: connectionLink) {
            DispatchQueue.main.async {
                dismiss?()
                connectionReqSentAlert(connReqType)
            }
        } else {
            DispatchQueue.main.async {
                dismiss?()
            }
        }
    }
}

struct CReqClientData: Decodable {
    var type: String
    var groupLinkId: String?
}

func parseLinkQueryData(_ connectionLink: String) -> CReqClientData? {
    if let hashIndex = connectionLink.firstIndex(of: "#"),
       let urlQuery = URL(string: String(connectionLink[connectionLink.index(after: hashIndex)...])),
       let components = URLComponents(url: urlQuery, resolvingAgainstBaseURL: false),
       let data = components.queryItems?.first(where: { $0.name == "data" })?.value,
       let d = data.data(using: .utf8),
       let crData = try? getJSONDecoder().decode(CReqClientData.self, from: d) {
        return crData
    } else {
        return nil
    }
}

func checkCRDataGroup(_ crData: CReqClientData) -> Bool {
    return crData.type == "group" && crData.groupLinkId != nil
}

func groupLinkAlert(_ connectionLink: String) -> Alert {
    return Alert(
        title: Text("Connect via group link?"),
        message: Text("You will join a group this link refers to and connect to its group members."),
        primaryButton: .default(Text("Connect")) {
            connectViaLink(connectionLink)
        },
        secondaryButton: .cancel()
    )
}

func connectionReqSentAlert(_ type: ConnReqType) {
    AlertManager.shared.showAlertMsg(
        title: "Connection request sent!",
        message: type == .contact
            ? "You will be connected when your connection request is accepted, please wait or check later!"
            : "You will be connected when your contact's device is online, please wait or check later!"
    )
}

struct NewChatButton_Previews: PreviewProvider {
    static var previews: some View {
        NewChatButton(showAddChat: Binding.constant(false))
    }
}
