import Foundation
import TelegramApi
import Postbox
import SwiftSignalKit
import MtProtoKit

private typealias SignalKitTimer = SwiftSignalKit.Timer


private final class NotificationAutolockReportManagerImpl {
    private let queue: Queue
    private let network: Network
    let isPerformingUpdate = ValuePromise<Bool>(false, ignoreRepeated: true)
    
    private var deadlineDisposable: Disposable?
    private let currentRequestDisposable = MetaDisposable()
    private var onlineTimer: SignalKitTimer?
    
    init(queue: Queue, deadline: Signal<Int32?, NoError>, network: Network) {
        self.queue = queue
        self.network = network
        
        self.deadlineDisposable = (deadline
        |> distinctUntilChanged
        |> deliverOn(self.queue)).start(next: { [weak self] value in
            self?.updateDeadline(value)
        })
    }
    
    deinit {
        assert(self.queue.isCurrent())
        self.deadlineDisposable?.dispose()
        self.currentRequestDisposable.dispose()
        self.onlineTimer?.invalidate()
    }
    
    private func updateDeadline(_ deadline: Int32?) {
        self.isPerformingUpdate.set(true)
        let value: Int32
        if let deadline = deadline {
            value = max(0, deadline - Int32(CFAbsoluteTimeGetCurrent()))
        } else {
            value = -1
        }
        self.currentRequestDisposable.set((self.network.request(Api.functions.account.updateDeviceLocked(period: value))
        |> `catch` { _ -> Signal<Api.Bool, NoError> in
            return .single(.boolFalse)
        }
        |> deliverOn(self.queue)).start(completed: { [weak self] in
            guard let strongSelf = self else {
                return
            }
            strongSelf.isPerformingUpdate.set(false)
        }))
    }
}

final class NotificationAutolockReportManager {
    private let queue = Queue()
    private let impl: QueueLocalObject<NotificationAutolockReportManagerImpl>
    
    init(deadline: Signal<Int32?, NoError>, network: Network) {
        let queue = self.queue
        self.impl = QueueLocalObject(queue: self.queue, generate: {
            return NotificationAutolockReportManagerImpl(queue: queue, deadline: deadline, network: network)
        })
    }
    
    func isPerformingUpdate() -> Signal<Bool, NoError> {
        return Signal { subscriber in
            let disposable = MetaDisposable()
            self.impl.with { impl in
                disposable.set(impl.isPerformingUpdate.get().start(next: { value in
                    subscriber.putNext(value)
                }))
            }
            return disposable
        }
    }
}