//
//  StoryPreviewVC.swift
//  CCSIMobile
//
//  Created by mac on 25/11/21.
//  Copyright © 2021 Milan Savaliya. All rights reserved.
//

import UIKit
import WowonderMessengerSDK
import Async
import Toast_Swift

protocol StoryPreviewVCDelegate {
    func handleStoryPreviewVCDismiss()
}

final class StoryPreviewVC: BaseVC {
    
    // MARK: - IBOutlet
    @IBOutlet weak private var clvStoryView: UICollectionView!
    
    // MARK: - Properties
    
    var delegate: StoryPreviewVCDelegate?
    private var needsDelayedScrolling = false
    private var firstLaunch = true
    var selectedStoryIndex = 0
    var arrayStories: [UserData] = []
    private var currentStoryIndex: Int?
    private var initialTouchPoint: CGPoint = CGPoint(x: 0, y: 0)
    private var displayBlurAtHeight: CGFloat = 200
    
    override var prefersStatusBarHidden: Bool {
        return true
    }
    
    // MARK: - View LifeCycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.setupUI()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.needsDelayedScrolling = true
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        if self.needsDelayedScrolling {
            self.needsDelayedScrolling = !self.needsDelayedScrolling
            let indexPath = IndexPath(item: self.selectedStoryIndex, section: 0)
            self.clvStoryView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: false)
        }
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        guard let cell = self.clvStoryView.visibleCells.get(at: 0) as? StoryCell else { return }
        cell.progressBar?.resetBar()
    }
    
    // MARK: - Helper Function
    
    private func setupUI() {
        let recognizer = UIPanGestureRecognizer(target: self, action: #selector(self.swipeDown(_:)))
        view.addGestureRecognizer(recognizer)
        NotificationCenter.default.addObserver(self, selector: #selector(self.appMovedToBackground), name: UIApplication.willResignActiveNotification, object: nil)
        self.setupCollectionView()
    }
    
    private func setupCollectionView() {
        self.clvStoryView.delegate = self
        self.clvStoryView.dataSource = self
        self.clvStoryView.register(UINib(resource: R.nib.storyCell), forCellWithReuseIdentifier: R.reuseIdentifier.storyCell.identifier)
        self.clvStoryView.isPagingEnabled = true
    }
    
    private func panGestureStateChnage(touchPoint: CGPoint) {
        if touchPoint.y - self.initialTouchPoint.y > 0 {
            self.clvStoryView.frame = CGRect(x: 0, y: touchPoint.y - self.initialTouchPoint.y + self.view.safeAreaTop, width: self.clvStoryView.frame.size.width, height: clvStoryView.frame.size.height)
            view.backgroundColor = UIColor(displayP3Red: 0, green: 0, blue: 0, alpha: 1 - (touchPoint.y - self.initialTouchPoint.y) / self.displayBlurAtHeight)
        }
    }
    
    private func panGestureStateCancelledAndEnded(touchPoint: CGPoint) {
        if touchPoint.y - self.initialTouchPoint.y > self.displayBlurAtHeight {
            self.dismiss(animated: true) {
                self.delegate?.handleStoryPreviewVCDismiss()
            }
        } else {
            UIView.animate(withDuration: 0.3, animations: {
                self.view.backgroundColor = .black
                self.clvStoryView.frame = CGRect(x: 0, y: self.view.safeAreaTop, width: self.clvStoryView.frame.size.width, height: self.clvStoryView.frame.size.height)
            })
        }
    }
    
    func showUpcomingUserStory() {
        let indexPath = IndexPath(item: (self.currentStoryIndex ?? 0), section: 0)
        self.clvStoryView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: false)
        self.clvStoryView.isUserInteractionEnabled = true
        var cell: StoryCell
        let visibleCells = self.clvStoryView.visibleCells
        if visibleCells.count > 1 {
            guard let mostVisableCell = self.scrollToMostVisibleCell(), let storyCell =  self.clvStoryView.cellForItem(at: mostVisableCell) as? StoryCell else { return }
            cell = storyCell
        } else {
            guard let storyCell = visibleCells.first as? StoryCell else { return }
            cell = storyCell
        }
        if cell.parentStoryIndex != self.currentStoryIndex {
            cell.progressBar?.resetBar()
            cell.progressBar?.animate(index: 0)
            cell.progressBar?.delegate?.segmentedProgressBarChangedIndex(index: 0)
        }
    }
    
    private func scrollDidEndDeceleratingAndDidEndScrollAnimation() {
        self.clvStoryView.isUserInteractionEnabled = true
        var cell: StoryCell
        let visibleCells = self.clvStoryView.visibleCells
        
        if visibleCells.count > 1 {
            guard let mostVisableCell = self.scrollToMostVisibleCell(), let storyCell =  self.clvStoryView.cellForItem(at: mostVisableCell) as? StoryCell else { return }
            cell = storyCell
        } else {
            guard let storyCell = visibleCells.first as? StoryCell else { return }
            cell = storyCell
        }
        
        if cell.parentStoryIndex != self.currentStoryIndex {
            cell.progressBar?.resetBar()
            cell.progressBar?.animate(index: 0)
            cell.progressBar?.delegate?.segmentedProgressBarChangedIndex(index: 0)
            self.currentStoryIndex = cell.parentStoryIndex
        }
    }
    
    @objc private func swipeDown(_ sender: UIPanGestureRecognizer) {
        let touchPoint = sender.location(in: view?.window)
        if sender.state == .began {
            self.initialTouchPoint = touchPoint
        } else if sender.state == .changed {
            self.panGestureStateChnage(touchPoint: touchPoint)
        } else if sender.state == .ended || sender.state == .cancelled {
            self.panGestureStateCancelledAndEnded(touchPoint: touchPoint)
        }
    }
    
    @objc private func appMovedToBackground() {
        guard let cell = self.clvStoryView.visibleCells.get(at: 0) as? StoryCell else { return }
        cell.progressBar?.pause()
    }
    
}

// MARK: - Extensions

// MARK: API Call
extension StoryPreviewVC {
    
    private func deleteStory(cell: StoryCell, story: UserDataStory) {
        if Connectivity.isConnectedToNetwork() {
            Async.background {
                StoriesManager.instance.deleteStory(session_Token: AppInstance.instance.sessionId ?? "", story_id: story.id?.stringValue ?? "", completionBlock: { (success, sessionError, serverError, error) in
                    if success != nil {
                        Async.main {
                            self.dismissProgressDialog {
                                cell.prepareForReuse()
                                self.dismiss(animated: true) {
                                    self.delegate?.handleStoryPreviewVCDismiss()
                                    appDelegate.window?.rootViewController?.view.makeToast("Story successfully deleted")
                                }
                            }
                        }
                    } else if sessionError != nil {
                        Async.main {
                            self.dismissProgressDialog {
                                self.view.makeToast(sessionError?.errors?.error_text)
                            }
                        }
                    } else if serverError != nil {
                        Async.main {
                            self.dismissProgressDialog {
                                self.view.makeToast(serverError?.errors?.error_text)
                            }
                        }
                    } else {
                        Async.main {
                            self.dismissProgressDialog {
                                self.view.makeToast(error?.localizedDescription)
                            }
                        }
                    }
                })
            }
        } else {
            self.dismissProgressDialog {
                self.view.makeToast(InterNetError)
            }
        }
    }
    
    // React Story Api Call
    private func reactStory(story_id: String, reaction: String) {
        Async.background {
            StoriesManager.instance.reactStory(story_id: story_id, reaction: reaction, completionBlock: { (success, sessionError, serverError, error) in
                if success != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            print(success?.message ?? "")
                        }
                    }
                } else if sessionError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(sessionError?.errors?.error_text)
                        }
                    }
                } else if serverError != nil {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(serverError?.errors?.error_text)
                        }
                    }
                } else {
                    Async.main {
                        self.dismissProgressDialog {
                            self.view.makeToast(error?.localizedDescription)
                        }
                    }
                }
            })
        }
    }
    
}

// MARK: CollectionView DataSource
extension StoryPreviewVC: UICollectionViewDataSource {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        self.arrayStories.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: R.reuseIdentifier.storyCell.identifier, for: indexPath) as! StoryCell
        cell.parentStoryIndex = indexPath.row
        cell.userData = self.arrayStories.get(at: indexPath.row)
        cell.setData()
        cell.initProgressbar()
        cell.delegate = self
        if self.firstLaunch && self.selectedStoryIndex == indexPath.row {
            cell.progressBar?.resetBar()
            cell.progressBar?.animate(index: 0)
            self.firstLaunch = false
            self.currentStoryIndex = self.selectedStoryIndex
        }
        cell.setStoryData(index: 0)
        return cell
    }
    
}

// MARK: CollectionView FlowLayout Delegate
extension StoryPreviewVC: UICollectionViewDelegateFlowLayout {
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: self.clvStoryView.frame.width, height: self.clvStoryView.frame.height)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
    
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        self.scrollDidEndDeceleratingAndDidEndScrollAnimation()
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if self.selectedStoryIndex == 0 && !self.firstLaunch {
            self.clvStoryView.isUserInteractionEnabled = false
        }
    }
    
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        self.scrollDidEndDeceleratingAndDidEndScrollAnimation()
    }
    
    func scrollToMostVisibleCell() -> IndexPath? {
        let visibleRect = CGRect(origin: self.clvStoryView.contentOffset, size: self.clvStoryView.bounds.size)
        let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
        if let visibleIndexPath: IndexPath = self.clvStoryView.indexPathForItem(at: visiblePoint) {
            return visibleIndexPath
        } else {
            return nil
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        guard let oldCell = cell as? StoryCell else { return }
        oldCell.progressBar?.resetBar()
    }
    
}

// MARK: StoryPreviewProtocol
extension StoryPreviewVC: StoryPreviewProtocol {
    
    func handleStoryReactionTap(reaction: Int, cell: StoryCell, story: UserDataStory) {
        self.reactStory(story_id: story.id?.stringValue ?? "", reaction: String(reaction))
    }    
    
    func handleStorySendMessageTap(_ sender: UIButton, cell: StoryCell, story: UserDataStory) {
        cell.pauseVideo()
        cell.progressBar?.pause()
        cell.storyReplyView.isHidden = true
        if let newVC = R.storyboard.story.storyReplyVC() {
            newVC.modalPresentationStyle = .overCurrentContext
            newVC.modalTransitionStyle = .crossDissolve
            newVC.delegate = self
            newVC.cell = cell
            newVC.story = story
            self.present(newVC, animated: true)
        }
    }
    
    func handleStoryViewsCountTap(_ sender: UIButton, cell: StoryCell, story: UserDataStory) {
        cell.pauseVideo()
        cell.progressBar?.pause()
        if let newVC = R.storyboard.story.storySeenUserListVC() {
            newVC.modalPresentationStyle = .custom
            newVC.transitioningDelegate = self
            newVC.delegate = self
            newVC.story = story
            newVC.cell = cell
            self.present(newVC, animated: true)
        }
    }
    
    func handleStoryBackButtonTap(_ sender: UIButton, cell: StoryCell) {
        cell.prepareForReuse()
        self.dismiss(animated: true) {
            self.delegate?.handleStoryPreviewVCDismiss()
        }
    }
    
    func handleStoryTrashButtonTap(_ sender: UIButton, cell: StoryCell, story: UserDataStory) {        
        self.deleteStory(cell: cell, story: story)
    }
    
    func segmentedProgressBarReachEnd(cell: StoryCell) {
        let newUserIndex = (self.currentStoryIndex ?? 0) + 1
        if newUserIndex < self.arrayStories.count {
            if self.selectedStoryIndex == 0 && !self.firstLaunch {
                self.clvStoryView.isUserInteractionEnabled = false
            }
            self.currentStoryIndex = newUserIndex
            self.showUpcomingUserStory()
        } else {
            cell.prepareForReuse()
            self.dismiss(animated: true, completion: nil)
        }
    }
    
    func segmentedProgressBarReachPrevious(cell: StoryCell) {
        let newIndex = (self.currentStoryIndex ?? 0) - 1
        if newIndex >= 0 {
            if self.selectedStoryIndex == 0 && !self.firstLaunch {
                self.clvStoryView.isUserInteractionEnabled = false
            }
            self.currentStoryIndex = newIndex
            self.showUpcomingUserStory()
        } else {
            cell.prepareForReuse()
            self.dismiss(animated: true, completion: nil)
        }
    }
    
}

// MARK: StorySeenUserListVCDelegate Methods
extension StoryPreviewVC: StorySeenUserListVCDelegate {
    
    func handleDismissStorySeenUserListVC(cell: StoryCell) {
        cell.playVideo()
        cell.progressBar?.resume()
    }
    
    func handleStorySeenUserListVCDeleteButtonTap(_ sender: UIButton, cell: StoryCell, story: UserDataStory) {        
        cell.playVideo()
        cell.progressBar?.resume()
        self.deleteStory(cell: cell, story: story)
    }
    
}

// MARK: StoryReplyVCDelegate Methods
extension StoryPreviewVC: StoryReplyVCDelegate {
    
    func handleDismissStoryReplyVC(cell: StoryCell) {
        cell.playVideo()
        cell.progressBar?.resume()
        cell.storyReplyView.isHidden = false
    }
    
}

// MARK: UIViewControllerTransitioningDelegate Methods
extension StoryPreviewVC: UIViewControllerTransitioningDelegate {
    
    func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
        if let VC = presented as? StorySeenUserListVC {
            let newVC = BottomSheetPresentationController(presentedViewController: presented, presenting: presenting)
            newVC.storyCell = VC.cell
            newVC.dismissDelegate = self
            return newVC
        } else {
            return BottomSheetPresentationController(presentedViewController: presented, presenting: presenting)
        }
    }
    
}
