//
//  PreferredControllerSkinsViewController.swift
//  Delta
//
//  Created by Riley Testut on 9/30/16.
//  Copyright © 2016 Riley Testut. All rights reserved.
//

import UIKit

import DeltaCore

extension PreferredControllerSkinsViewController
{
    private enum Section: Int
    {
        case portrait
        case landscape
    }
}

class PreferredControllerSkinsViewController: UITableViewController
{
    var system: System!
    
    var game: Game? {
        didSet {
            guard let game = self.game, let system = System(gameType: game.type) else { return }
            self.system = system
        }
    }
    
    @IBOutlet private var portraitImageView: UIImageView!
    @IBOutlet private var landscapeImageView: UIImageView!
    
    private var _previousBoundsSize: CGSize?
    private var portraitControllerSkin: ControllerSkin?
    private var landscapeControllerSkin: ControllerSkin?
}

extension PreferredControllerSkinsViewController
{
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        self.title = self.game?.name ?? self.system.localizedShortName
        
        if self.navigationController?.viewControllers.first != self
        {
            // Hide Done button since we are not root view controller.
            self.navigationItem.rightBarButtonItem = nil
        }
    }
    
    override func viewDidDisappear(_ animated: Bool)
    {
        super.viewDidDisappear(animated)
        
        self._previousBoundsSize = nil
    }

    override func didReceiveMemoryWarning()
    {
        super.didReceiveMemoryWarning()
    }
    
    override func viewDidLayoutSubviews()
    {
        super.viewDidLayoutSubviews()
        
        if self.view.bounds.size != self._previousBoundsSize
        {
            self.updateControllerSkins()
            self.tableView.reloadData()
        }
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?)
    {
        guard let cell = sender as? UITableViewCell, let indexPath = self.tableView.indexPath(for: cell), let window = self.view.window else { return }
        
        let controllerSkinsViewController = segue.destination as! ControllerSkinsViewController
        controllerSkinsViewController.delegate = self
        controllerSkinsViewController.system = self.system
        
        var traits = DeltaCore.ControllerSkin.Traits.defaults(for: window)
        
        let section = Section(rawValue: indexPath.section)!
        switch section
        {
        case .portrait: traits.orientation = .portrait
        case .landscape: traits.orientation = .landscape
        }
        
        controllerSkinsViewController.traits = traits
        
        let isResetButtonVisible: Bool
        
        if let game = self.game
        {
            switch section
            {
            case .portrait: isResetButtonVisible = (game.preferredPortraitSkin != nil)
            case .landscape: isResetButtonVisible = (game.preferredLandscapeSkin != nil)
            }
        }
        else
        {
            switch section
            {
            case .portrait: isResetButtonVisible = !(self.portraitControllerSkin?.isStandard ?? false)
            case .landscape: isResetButtonVisible = !(self.portraitControllerSkin?.isStandard ?? false)
            }
        }
        
        controllerSkinsViewController.isResetButtonVisible = isResetButtonVisible
    }
}

extension PreferredControllerSkinsViewController
{
    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
    {
        guard let window = self.view.window else { return 44.0 }
        
        let section = Section(rawValue: indexPath.section)!
        
        let aspectRatio: CGSize?
        
        switch section
        {
        case .portrait: aspectRatio = self.portraitControllerSkin?.aspectRatio(for: self.makeTraits(orientation: .portrait, in: window))
        case .landscape: aspectRatio = self.landscapeControllerSkin?.aspectRatio(for: self.makeTraits(orientation: .landscape, in: window))
        }
        
        guard let unwrappedAspectRatio = aspectRatio else { return super.tableView(tableView, heightForRowAt: indexPath) }
        
        let scale = (self.view.bounds.width / unwrappedAspectRatio.width)
        
        let height = min(unwrappedAspectRatio.height * scale, self.view.bounds.height - self.view.safeAreaInsets.top - self.view.safeAreaInsets.bottom - 30)
        return height
    }
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    {
        guard let cell = tableView.cellForRow(at: indexPath) else { return }
        
        self.performSegue(withIdentifier: "showControllerSkins", sender: cell)
    }
}

private extension PreferredControllerSkinsViewController
{
    func updateControllerSkins()
    {
        guard let window = self.view.window else { return }
        
        self._previousBoundsSize = self.view.bounds.size
                
        let portraitTraits = self.makeTraits(orientation: .portrait, in: window)
        let landscapeTraits = self.makeTraits(orientation: .landscape, in: window)
        
        var portraitControllerSkin: ControllerSkin?
        var landscapeControllerSkin: ControllerSkin?
        
        if let game = self.game
        {
            portraitControllerSkin = Settings.preferredControllerSkin(for: game, traits: portraitTraits)
            landscapeControllerSkin = Settings.preferredControllerSkin(for: game, traits: landscapeTraits)
        }
        
        if portraitControllerSkin == nil
        {
            portraitControllerSkin = Settings.preferredControllerSkin(for: self.system, traits: portraitTraits)
        }
        
        if landscapeControllerSkin == nil
        {
            landscapeControllerSkin = Settings.preferredControllerSkin(for: self.system, traits: landscapeTraits)
        }
        
        if portraitControllerSkin != self.portraitControllerSkin
        {
            self.portraitImageView.image = nil
            self.portraitImageView.isIndicatingActivity = true
            
            self.portraitControllerSkin = portraitControllerSkin
        }
        
        if landscapeControllerSkin != self.landscapeControllerSkin
        {
            self.landscapeImageView.image = nil
            self.landscapeImageView.isIndicatingActivity = true
            
            self.landscapeControllerSkin = landscapeControllerSkin
        }
        
        DatabaseManager.shared.performBackgroundTask { (context) in
            
            let portraitImage: UIImage?
            let landscapeImage: UIImage?
            
            if let portraitControllerSkin = self.portraitControllerSkin
            {
                let skin = context.object(with: portraitControllerSkin.objectID) as! ControllerSkin
                portraitImage = skin.image(for: portraitTraits, preferredSize: UIScreen.main.defaultControllerSkinSize)
            }
            else
            {
                portraitImage = nil
            }
            
            if let landscapeControllerSkin = self.landscapeControllerSkin
            {
                let skin = context.object(with: landscapeControllerSkin.objectID) as! ControllerSkin
                landscapeImage = skin.image(for: landscapeTraits, preferredSize: UIScreen.main.defaultControllerSkinSize)
            }
            else
            {
                landscapeImage = nil
            }
            
            DispatchQueue.main.async {
                self.portraitImageView.isIndicatingActivity = false
                self.portraitImageView.image = portraitImage
                
                self.landscapeImageView.isIndicatingActivity = false
                self.landscapeImageView.image = landscapeImage
            }
        }
    }
    
    func makeTraits(orientation: DeltaCore.ControllerSkin.Orientation, in window: UIWindow) -> DeltaCore.ControllerSkin.Traits
    {
        var traits = DeltaCore.ControllerSkin.Traits.defaults(for: window)
        traits.orientation = orientation
        return traits
    }
}

extension PreferredControllerSkinsViewController: ControllerSkinsViewControllerDelegate
{
    func controllerSkinsViewController(_ controllerSkinsViewController: ControllerSkinsViewController, didChooseControllerSkin controllerSkin: ControllerSkin)
    {
        if let game = self.game
        {
            Settings.setPreferredControllerSkin(controllerSkin, for: game, traits: controllerSkinsViewController.traits)
        }
        else
        {
            Settings.setPreferredControllerSkin(controllerSkin, for: self.system, traits: controllerSkinsViewController.traits)
        }
        
        _ = self.navigationController?.popViewController(animated: true)
    }
    
    func controllerSkinsViewControllerDidResetControllerSkin(_ controllerSkinsViewController: ControllerSkinsViewController)
    {
        if let game = self.game
        {
            Settings.setPreferredControllerSkin(nil, for: game, traits: controllerSkinsViewController.traits)
        }
        else
        {
            Settings.setPreferredControllerSkin(nil, for: self.system, traits: controllerSkinsViewController.traits)
        }
        
        _ = self.navigationController?.popViewController(animated: true)
    }
}
