<commit_before>//
//  This file is part of Blokada.
//
//  This Source Code Form is subject to the terms of the Mozilla Public
//  License, v. 2.0. If a copy of the MPL was not distributed with this
//  file, You can obtain one at https://mozilla.org/MPL/2.0/.
//
//  Copyright © 2021 Blocka AB. All rights reserved.
//
//  @author <NAME>
//

import Foundation
import Combine

typealias Granted = Bool

class PermsRepo {

    var dnsProfilePerms: AnyPublisher<Granted, Never> {
        writeDnsProfilePerms.compactMap { $0 }.removeDuplicates().eraseToAnyPublisher()
    }

    var vpnProfilePerms: AnyPublisher<Granted, Never> {
        writeVpnProfilePerms.compactMap { $0 }.removeDuplicates().eraseToAnyPublisher()
    }

    var notificationPerms: AnyPublisher<Granted, Never> {
        writeNotificationPerms.compactMap { $0 }.removeDuplicates().eraseToAnyPublisher()
    }

    private lazy var notification = Services.notification
    private lazy var dialog = Services.dialog
    private lazy var systemNav = Services.systemNav

    private lazy var sheetRepo = Repos.sheetRepo
    private lazy var netxRepo = Repos.netxRepo
    private lazy var dnsProfileActivatedHot = Repos.cloudRepo.dnsProfileActivatedHot
    private lazy var enteredForegroundHot = Repos.stageRepo.enteredForegroundHot
    private lazy var successfulPurchasesHot = Repos.paymentRepo.successfulPurchasesHot
    private lazy var accountTypeHot = Repos.accountRepo.accountTypeHot

    fileprivate let writeDnsProfilePerms = CurrentValueSubject<Granted?, Never>(nil)
    fileprivate let writeVpnProfilePerms = CurrentValueSubject<Granted?, Never>(nil)
    fileprivate let writeNotificationPerms = CurrentValueSubject<Granted?, Never>(nil)

    private var previousAccountType: AccountType? = nil
    private let bgQueue = DispatchQueue(label: "PermsRepoBgQueue")
    private var cancellables = Set<AnyCancellable>()

    init() {
        onDnsProfileActivated()
        onForeground_checkNotificationPermsAndClearNotifications()
        onVpnPerms()
        onPurchaseSuccessful_showActivatedSheet()
        onAccountTypeUpgraded_showActivatedSheet()
    }

    func maybeDisplayDnsProfilePermsDialog() -> AnyPublisher<Ignored, Error> {
        return dnsProfilePerms.first()
        .tryMap { granted -> Ignored in
            if !granted {
                throw "show the dns profile dialog"
            } else {
                return true
            }
        }
        .tryCatch { _ in
            self.displayDnsProfilePermsInstructions()
            .tryMap { _ in throw "we never know if dns profile has been chosen" }
        }
        .eraseToAnyPublisher()
    }

    func maybeAskVpnProfilePerms() -> AnyPublisher<Granted, Error> {
        return vpnProfilePerms.first()
        .tryMap { granted -> Ignored in
            if !granted {
                throw "ask for vpn profile"
            } else {
                return true
            }
        }
        .tryCatch { _ in self.netxRepo.createVpnProfile() }
        .eraseToAnyPublisher()
    }

    func askNotificationPerms() -> AnyPublisher<Granted, Error> {
        return notification.askForPermissions()
        .tryCatch { err in
            self.dialog.showAlert(<commit_msg>ios: fix asking for vpn when not plus<commit_after>//
//  This file is part of Blokada.
//
//  This Source Code Form is subject to the terms of the Mozilla Public
//  License, v. 2.0. If a copy of the MPL was not distributed with this
//  file, You can obtain one at https://mozilla.org/MPL/2.0/.
//
//  Copyright © 2021 Blocka AB. All rights reserved.
//
//  @author <NAME>
//

import Foundation
import Combine

typealias Granted = Bool

class PermsRepo {

    var dnsProfilePerms: AnyPublisher<Granted, Never> {
        writeDnsProfilePerms.compactMap { $0 }.removeDuplicates().eraseToAnyPublisher()
    }

    var vpnProfilePerms: AnyPublisher<Granted, Never> {
        writeVpnProfilePerms.compactMap { $0 }.removeDuplicates().eraseToAnyPublisher()
    }

    var notificationPerms: AnyPublisher<Granted, Never> {
        writeNotificationPerms.compactMap { $0 }.removeDuplicates().eraseToAnyPublisher()
    }

    private lazy var notification = Services.notification
    private lazy var dialog = Services.dialog
    private lazy var systemNav = Services.systemNav

    private lazy var sheetRepo = Repos.sheetRepo
    private lazy var netxRepo = Repos.netxRepo
    private lazy var dnsProfileActivatedHot = Repos.cloudRepo.dnsProfileActivatedHot
    private lazy var enteredForegroundHot = Repos.stageRepo.enteredForegroundHot
    private lazy var successfulPurchasesHot = Repos.paymentRepo.successfulPurchasesHot
    private lazy var accountTypeHot = Repos.accountRepo.accountTypeHot

    fileprivate let writeDnsProfilePerms = CurrentValueSubject<Granted?, Never>(nil)
    fileprivate let writeVpnProfilePerms = CurrentValueSubject<Granted?, Never>(nil)
    fileprivate let writeNotificationPerms = CurrentValueSubject<Granted?, Never>(nil)

    private var previousAccountType: AccountType? = nil
    private let bgQueue = DispatchQueue(label: "PermsRepoBgQueue")
    private var cancellables = Set<AnyCancellable>()

    init() {
        onDnsProfileActivated()
        onForeground_checkNotificationPermsAndClearNotifications()
        onVpnPerms()
        onPurchaseSuccessful_showActivatedSheet()
        onAccountTypeUpgraded_showActivatedSheet()
    }

    func maybeDisplayDnsProfilePermsDialog() -> AnyPublisher<Ignored, Error> {
        return dnsProfilePerms.first()
        .tryMap { granted -> Ignored in
            if !granted {
                throw "show the dns profile dialog"
            } else {
                return true
            }
        }
        .tryCatch { _ in
            self.displayDnsProfilePermsInstructions()
            .tryMap { _ in throw "we never know if dns profile has been chosen" }
        }
        .eraseToAnyPublisher()
    }

    func maybeAskVpnProfilePerms() -> AnyPublisher<Granted, Error> {
        return accountTypeHot.first()
        .flatMap { it -> AnyPublisher<Granted, Error> in
            if it == .Plus {
                return self.vpnProfilePerms.first()
                .tryMap { granted -> Ignored in
                    if !granted {
                        throw "ask for vpn profile"
                    } else {
                        return true
                    }
                }
                .eraseToAnyPublisher()
            } else {
                return Just(true)
                .setFailureType(to: Error.self)
                .eraseToAnyPublisher()
            }
        }
        .tryCatch { _ in self.netxRepo.createVpnProfile() }
        .eraseToAnyPublisher()
    }

    func askNotificationPerms() -> AnyPublisher<Granted, Error> {
        return notification.askForPermissions()
        .tryCatch { err in
            self.dialog.showAlert(
{'fraction_non_alphanumeric': 0.07897033158813263, 'fraction_numerical': 0.0031995346131471784, 'mean_word_length': 2.5558428128231645, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 37, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3291587', 'n_tokens_mistral': 1996, 'n_tokens_neox': 1893, 'n_words': 487}