//
/*
 * Copyright (c) 2021 BWI GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import UIKit

final class RoomRollsAndRightsViewController: UITableViewController {
    
    private var viewModel: RoomRollsAndRightsViewModelType!
    private var state: RoomRollsAndRightsViewState?
    private var theme: Theme!
    private var errorPresenter: MXKErrorPresentation!
    private var activityPresenter: ActivityIndicatorPresenter!
    
    // MARK: - Setup

    class func instantiate(with viewModel: RoomRollsAndRightsViewModelType) -> RoomRollsAndRightsViewController {
        let viewController = RoomRollsAndRightsViewController()
        viewController.viewModel = viewModel
        viewController.theme = ThemeService.shared().theme
        return viewController
    }

    // MARK: - Life cycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupViews()
        
        self.tableView.dataSource = self
        self.tableView.delegate = self
        
        // Do any additional setup after loading the view.
        
        activityPresenter = ActivityIndicatorPresenter()
        errorPresenter = MXKErrorAlertPresentation()
        
        registerThemeServiceDidChangeThemeNotification()
        update(theme: theme)
        
        viewModel.viewDelegate = self
        viewModel.process(viewAction: .load)
    }
    
    private func setupViews() {
        
        tableView.contentInsetAdjustmentBehavior = .never
        
        self.title = BWIL10n.bwiRollsAndRightsMainTitle
        
        let doneBarButtonItem = MXKBarButtonItem(title: VectorL10n.roomNotifsSettingsDoneAction, style: .plain) { [weak self] in
            self?.viewModel.process(viewAction: .save)
        }
        
        let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.roomNotifsSettingsCancelAction, style: .plain) { [weak self] in
            self?.viewModel.process(viewAction: .cancel)
        }
        
        if navigationController?.navigationBar.backItem == nil {
            navigationItem.leftBarButtonItem = cancelBarButtonItem
        }
        if viewModel.isCurrentUserAdmin() {
            navigationItem.rightBarButtonItem = doneBarButtonItem
        }
    }

    // MARK: - Theme
    
    private func update(theme: Theme) {
        self.theme = theme
        
        view.backgroundColor = theme.headerBackgroundColor
        self.tableView.backgroundColor = theme.headerBackgroundColor
        self.tableView.separatorColor = theme.textSecondaryColor
        
        if let navigationBar = navigationController?.navigationBar {
            theme.applyStyle(onNavigationBar: navigationBar)
        }
        self.tableView.reloadData()
    }

    private func registerThemeServiceDidChangeThemeNotification() {
        NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil)
    }
    
    @objc private func themeDidChange() {
        update(theme: ThemeService.shared().theme)
    }

}

// MARK: - UITableViewDataSource

extension RoomRollsAndRightsViewController {
    
    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let textView = UITextView()
        textView.isUserInteractionEnabled = false
        textView.textContainerInset = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
        textView.font = UIFont.systemFont(ofSize: 15)
        textView.textColor = theme.headerTextPrimaryColor
        textView.backgroundColor = theme.headerBackgroundColor
        if viewModel.isCurrentUserAdmin() {
            textView.text = BWIL10n.bwiRollsAndRightsMainHeaderAdmin
        } else {
            textView.text = BWIL10n.bwiRollsAndRightsMainHeaderNoAdmin
        }
        return textView
    }
    override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return 80
    }
    
    override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        if viewModel.isCurrentUserAdmin() {
            let button = UIButton(type: .custom)
            button.setTitle(BWIL10n.bwiRollsAndRightsResetButton, for: .normal)
            button.addTarget(self, action: #selector(onButtonReset(_:)), for: .touchUpInside)
            button.setTitleColor(theme.tintColor, for: .normal)
            button.backgroundColor = theme.headerBackgroundColor
            return button
        } else {
            let emptyView = UIView()
            emptyView.backgroundColor = theme.headerBackgroundColor
            return emptyView
        }
    }
    
    @objc
    private func onButtonReset(_ sender: UIButton) {
        resetToDefaults()
    }
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = indexPath.row < 5 ? UITableViewCell(style: .subtitle, reuseIdentifier: "rolls_and_rights_cells") : UITableViewCell(style: .default, reuseIdentifier: "rolls_and_rights_button_cells")
        
        cell.selectionStyle = .none
        cell.accessoryType = viewModel.isCurrentUserAdmin() ? .disclosureIndicator : .none
        cell.tintColor = .blue
        cell.textLabel?.numberOfLines = 0
        cell.textLabel?.textColor = theme.textPrimaryColor
        cell.detailTextLabel?.textColor = theme.textSecondaryColor
        cell.backgroundColor = theme.backgroundColor
        
        switch indexPath.row {
        case 0:
            cell.textLabel?.text = BWIL10n.bwiRollsAndRightsGeneral
            cell.detailTextLabel?.text = roll(for: state?.powerLevelGeneral)
        case 1:
            cell.textLabel?.text = BWIL10n.bwiRollsAndRightsSend
            cell.detailTextLabel?.text = roll(for: state?.powerLevelSend)
        case 2:
            cell.textLabel?.text = BWIL10n.bwiRollsAndRightsInvite
            cell.detailTextLabel?.text = roll(for: state?.powerLevelInvite)
        case 3:
            cell.textLabel?.text = BWIL10n.bwiRollsAndRightsRedact
            cell.detailTextLabel?.text = roll(for: state?.powerLevelRedact)
        case 4:
            cell.textLabel?.text = BWIL10n.bwiRollsAndRightsBan
            cell.detailTextLabel?.text = roll(for: state?.powerLevelBan)
        case 5:
            cell.textLabel?.text = BWIL10n.bwiRollsAndRightsResetButton
        default:
            assertionFailure("invalid indexPath in RollsAndRightsViewController tableview")
        }
        return cell
    }

    private func roll(for powerlevel: Int?) -> String? {
        guard let powerlevel = powerlevel else {
            return nil
        }
        
        if powerlevel >= RoomPowerLevel.admin.rawValue {
            return BWIL10n.bwiRollsAndRightsAdmin
        }
        else if powerlevel >= RoomPowerLevel.moderator.rawValue {
            return BWIL10n.bwiRollsAndRightsModerator
        }
        else {
            return BWIL10n.bwiRollsAndRightsUser
        }
    }
}

// MARK: - UITableViewDelegate

extension RoomRollsAndRightsViewController {
    
    override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
        return viewModel.isCurrentUserAdmin() ? indexPath : nil
    }
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let viewController = RoomRollsAndRightsPickerViewController()
        viewController.delegate = self.viewModel as? RoomRollsAndRightsPickerViewControllerDelegate
        viewController.viewState = self.state
        viewController.theme = ThemeService.shared().theme
        
        switch indexPath.row {
        case 0:
            viewController.selectedViewStateProperty = .general
        case 1:
            viewController.selectedViewStateProperty = .send
        case 2:
            viewController.selectedViewStateProperty = .invite
        case 3:
            viewController.selectedViewStateProperty = .redact
        case 4:
            viewController.selectedViewStateProperty = .ban
        default:
            assertionFailure("invalid indexPath in RollsAndRightsViewController tableview")
        }
        self.navigationController?.pushViewController(viewController, animated: true)
    }
    
    private func resetToDefaults() {
        let alert = UIAlertController(title: BWIL10n.bwiRollsAndRightsResetButton,
                                      message: BWIL10n.bwiRollsAndRightsResetTitle,
                                      preferredStyle: .alert)
        
        let cancelActionTitle = BWIL10n.bwiRollsAndRightsResetCancel
        let cancelAction = UIAlertAction(title: cancelActionTitle, style: .cancel)
        
        let resetPowerLevelsActionTitle = BWIL10n.bwiRollsAndRightsResetOk
        let resetPowerLevelsAction = UIAlertAction(title: resetPowerLevelsActionTitle, style: .default, handler: { _ in
            self.viewModel.process(viewAction: .reset)
        })
        
        alert.addAction(cancelAction)
        alert.addAction(resetPowerLevelsAction)
        
        present(alert, animated: true, completion: nil)
    }
}

// MARK: - RoomNRollsAndRightsViewModelViewDelegate

extension RoomRollsAndRightsViewController: RoomRollsAndRightsViewModelViewDelegate {

    func roomRollsAndRightsViewModel(_ viewModel: RoomRollsAndRightsViewModelType, didUpdateViewState viewState: RoomRollsAndRightsViewState) {
        self.state = viewState
        self.tableView.reloadData()
    }
}
