// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.

import UIKit
import QuartzCore
import GRDB
import DifferenceKit
import SessionUIKit
import SignalUtilitiesKit
import SignalCoreKit

public class AllMediaViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
    private let pageVC = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
    private var pages: [UIViewController] = []
    private var targetVCIndex: Int?
    
    // MARK: - Components
    
    private lazy var tabBar: TabBar = {
        let result: TabBar = TabBar(
            tabs: [
                TabBar.Tab(title: MediaStrings.media) { [weak self] in
                    guard let self = self else { return }
                    self.pageVC.setViewControllers([ self.pages[0] ], direction: .forward, animated: false, completion: nil)
                    self.updateSelectButton(updatedData: self.mediaTitleViewController.viewModel.galleryData, inBatchSelectMode: self.mediaTitleViewController.isInBatchSelectMode)
                },
                TabBar.Tab(title: MediaStrings.document) { [weak self] in
                    guard let self = self else { return }
                    self.pageVC.setViewControllers([ self.pages[1] ], direction: .forward, animated: false, completion: nil)
                    self.endSelectMode()
                    self.navigationItem.rightBarButtonItem = nil
                }
            ]
        )
        result.themeBackgroundColor = .backgroundPrimary
        
        return result
    }()
    
    private var mediaTitleViewController: MediaTileViewController
    private var documentTitleViewController: DocumentTileViewController
    
    init(mediaTitleViewController: MediaTileViewController, documentTitleViewController: DocumentTileViewController) {
        self.mediaTitleViewController = mediaTitleViewController
        self.documentTitleViewController = documentTitleViewController
        
        super.init(nibName: nil, bundle: nil)
        
        self.mediaTitleViewController.delegate = self
        self.documentTitleViewController.delegate = self
        
        addChild(self.mediaTitleViewController)
        addChild(self.documentTitleViewController)
    }
    
    required init?(coder: NSCoder) {
        notImplemented()
    }
    
    // MARK: Lifecycle
    public override func viewDidLoad() {
        super.viewDidLoad()
        
        view.themeBackgroundColor = .newConversation_background
        
        // Add a custom back button if this is the only view controller
        if self.navigationController?.viewControllers.first == self {
            let backButton = UIViewController.createOWSBackButton(target: self, selector: #selector(didPressDismissButton))
            self.navigationItem.leftBarButtonItem = backButton
        }
        
        ViewControllerUtilities.setUpDefaultSessionStyle(
            for: self,
            title: MediaStrings.allMedia,
            hasCustomBackButton: false
        )
        
        // Set up page VC
        pages = [ mediaTitleViewController, documentTitleViewController ]
        pageVC.dataSource = self
        pageVC.delegate = self
        pageVC.setViewControllers([ mediaTitleViewController ], direction: .forward, animated: false, completion: nil)
        addChild(pageVC)
        
        // Set up tab bar
        view.addSubview(tabBar)
        tabBar.pin([ UIView.HorizontalEdge.leading, UIView.HorizontalEdge.trailing, UIView.VerticalEdge.top ], to: view)
        // Set up page VC constraints
        let pageVCView = pageVC.view!
        view.addSubview(pageVCView)
        pageVCView.pin([ UIView.HorizontalEdge.leading, UIView.HorizontalEdge.trailing, UIView.VerticalEdge.bottom ], to: view)
        pageVCView.pin(.top, to: .bottom, of: tabBar)
    }
    
    // MARK: General
    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let index = pages.firstIndex(of: viewController), index != 0 else { return nil }
        return pages[index - 1]
    }
    
    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let index = pages.firstIndex(of: viewController), index != (pages.count - 1) else { return nil }
        return pages[index + 1]
    }
    
    // MARK: Updating
    public func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
        guard let targetVC = pendingViewControllers.first, let index = pages.firstIndex(of: targetVC) else { return }
        targetVCIndex = index
    }
    
    public func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating isFinished: Bool, previousViewControllers: [UIViewController], transitionCompleted isCompleted: Bool) {
        guard isCompleted, let index = targetVCIndex else { return }
        tabBar.selectTab(at: index)
    }
    
    // MARK: Interaction
    @objc public func didPressDismissButton() {
        dismiss(animated: true, completion: nil)
    }
    
    // MARK: Batch Selection
    @objc func didTapSelect(_ sender: Any) {
        self.mediaTitleViewController.didTapSelect(sender)

        // Don't allow the user to leave mid-selection, so they realized they have
        // to cancel (lose) their selection if they leave.
        self.navigationItem.hidesBackButton = true
    }

    @objc func didCancelSelect(_ sender: Any) {
        endSelectMode()
    }

    func endSelectMode() {
        self.mediaTitleViewController.endSelectMode()
        self.navigationItem.hidesBackButton = false
    }
}

// MARK: - UIDocumentInteractionControllerDelegate

extension AllMediaViewController: UIDocumentInteractionControllerDelegate {
    public func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        return self
    }
}

// MARK: - DocumentTitleViewControllerDelegate

extension AllMediaViewController: DocumentTileViewControllerDelegate {
    public func share(fileUrl: URL) {
        let shareVC = UIActivityViewController(activityItems: [ fileUrl ], applicationActivities: nil)
        
        if UIDevice.current.isIPad {
            shareVC.excludedActivityTypes = []
            shareVC.popoverPresentationController?.permittedArrowDirections = []
            shareVC.popoverPresentationController?.sourceView = self.view
            shareVC.popoverPresentationController?.sourceRect = self.view.bounds
        }
        
        navigationController?.present(shareVC, animated: true, completion: nil)
    }
    
    public func preview(fileUrl: URL) {
        let interactionController: UIDocumentInteractionController = UIDocumentInteractionController(url: fileUrl)
        interactionController.delegate = self
        interactionController.presentPreview(animated: true)
    }
}

// MARK: - DocumentTitleViewControllerDelegate

extension AllMediaViewController: MediaTileViewControllerDelegate {
    public func presentdetailViewController(_ detailViewController: UIViewController, animated: Bool) {
        self.present(detailViewController, animated: animated)
    }
    
    public func updateSelectButton(updatedData: [MediaGalleryViewModel.SectionModel], inBatchSelectMode: Bool) {
        guard !updatedData.isEmpty else {
            self.navigationItem.rightBarButtonItem = nil
            return
        }
        
        if inBatchSelectMode {
            self.navigationItem.rightBarButtonItem = UIBarButtonItem(
                barButtonSystemItem: .cancel,
                target: self,
                action: #selector(didCancelSelect)
            )
        }
        else {
            self.navigationItem.rightBarButtonItem = UIBarButtonItem(
                title: "BUTTON_SELECT".localized(),
                style: .plain,
                target: self,
                action: #selector(didTapSelect)
            )
        }
    }
}

// MARK: - UIViewControllerTransitioningDelegate

extension AllMediaViewController: UIViewControllerTransitioningDelegate {
    public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self.mediaTitleViewController.animationController(forPresented: presented, presenting: presenting, source: source)
    }

    public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self.mediaTitleViewController.animationController(forDismissed: dismissed)
    }
}


// MARK: - MediaPresentationContextProvider

extension AllMediaViewController: MediaPresentationContextProvider {
    func mediaPresentationContext(mediaItem: Media, in coordinateSpace: UICoordinateSpace) -> MediaPresentationContext? {
        return self.mediaTitleViewController.mediaPresentationContext(mediaItem: mediaItem, in: coordinateSpace)
    }

    func snapshotOverlayView(in coordinateSpace: UICoordinateSpace) -> (UIView, CGRect)? {
        return self.mediaTitleViewController.snapshotOverlayView(in: coordinateSpace)
    }
}