import Foundation
import UIKit
import Display
import AsyncDisplayKit
import Postbox
import TelegramCore
import TelegramPresentationData
import ChatPresentationInterfaceState

private enum ChatInfoTitleButton {
    case search
    case info
    case mute
    case unmute
    case call
    case report
    case unarchive
    
    func title(_ strings: PresentationStrings) -> String {
        switch self {
            case .search:
                return strings.Common_Search
            case .info:
                return strings.Conversation_Info
            case .mute:
                return strings.Conversation_TitleMute
            case .unmute:
                return strings.Conversation_TitleUnmute
            case .call:
                return strings.Conversation_Call
            case .report:
                return strings.ReportPeer_Report
            case .unarchive:
                return strings.ChatList_UnarchiveAction
        }
    }
    
    func icon(_ theme: PresentationTheme) -> UIImage? {
        switch self {
            case .search:
                return PresentationResourcesChat.chatTitlePanelSearchImage(theme)
            case .info:
                return PresentationResourcesChat.chatTitlePanelInfoImage(theme)
            case .mute:
                return PresentationResourcesChat.chatTitlePanelMuteImage(theme)
            case .unmute:
                return PresentationResourcesChat.chatTitlePanelUnmuteImage(theme)
            case .call:
                return PresentationResourcesChat.chatTitlePanelCallImage(theme)
            case .report:
                return PresentationResourcesChat.chatTitlePanelReportImage(theme)
            case .unarchive:
                return PresentationResourcesChat.chatTitlePanelUnarchiveImage(theme)
        }
    }
}

private func peerButtons(_ peer: Peer, interfaceState: ChatPresentationInterfaceState) -> [ChatInfoTitleButton] {
    let muteAction: ChatInfoTitleButton
    if interfaceState.peerIsMuted {
        muteAction = .unmute
    } else {
        muteAction = .mute
    }
    
    let infoButton: ChatInfoTitleButton
    if interfaceState.isArchived {
        infoButton = .unarchive
    } else {
        infoButton = .info
    }
    
    if let peer = peer as? TelegramUser {
        var buttons: [ChatInfoTitleButton] = [.search, muteAction]
        if peer.botInfo == nil && interfaceState.callsAvailable {
            buttons.append(.call)
        }
        
        buttons.append(infoButton)
        return buttons
    } else if let _ = peer as? TelegramSecretChat {
        var buttons: [ChatInfoTitleButton] = [.search, muteAction]
        buttons.append(.call)
        buttons.append(.info)
        return buttons
    } else if let channel = peer as? TelegramChannel {
        if channel.flags.contains(.isCreator) || channel.username == nil {
            return [.search, muteAction, infoButton]
        } else {
            return [.search, .report, muteAction, infoButton]
        }
    } else if let group = peer as? TelegramGroup {
        if case .creator = group.role {
            return [.search, muteAction, infoButton]
        } else {
            return [.search, muteAction, infoButton]
        }
    } else {
        return [.search, muteAction, infoButton]
    }
}

private let buttonFont = Font.medium(10.0)

private final class ChatInfoTitlePanelButtonNode: HighlightableButtonNode {
    init() {
        super.init()
        
        self.displaysAsynchronously = false
        self.imageNode.displayWithoutProcessing = true
        self.imageNode.displaysAsynchronously = false
        
        self.titleNode.displaysAsynchronously = false
        
        self.laysOutHorizontally = false
    }
    
    func setup(text: String, color: UIColor, icon: UIImage?) {
        self.setTitle(text, with: buttonFont, with: color, for: [])
        self.setImage(icon, for: [])
        if let icon = icon {
            self.contentSpacing = max(0.0, 32.0 - icon.size.height)
        }
    }
}

final class ChatInfoTitlePanelNode: ChatTitleAccessoryPanelNode {
    private var theme: PresentationTheme?

    private let separatorNode: ASDisplayNode
    private var buttons: [(ChatInfoTitleButton, ChatInfoTitlePanelButtonNode)] = []
    
    override init() {
        self.separatorNode = ASDisplayNode()
        self.separatorNode.isLayerBacked = true
        
        super.init()

        self.addSubnode(self.separatorNode)
    }
    
    override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) -> LayoutResult {
        let themeUpdated = self.theme !== interfaceState.theme
        self.theme = interfaceState.theme
        
        let panelHeight: CGFloat = 55.0
        
        if themeUpdated {
            self.separatorNode.backgroundColor = interfaceState.theme.rootController.navigationBar.separatorColor
        }
        
        let updatedButtons: [ChatInfoTitleButton]
        switch interfaceState.chatLocation {
        case .peer:
            if let peer = interfaceState.renderedPeer?.peer {
                updatedButtons = peerButtons(peer, interfaceState: interfaceState)
            } else {
                updatedButtons = []
            }
        case .replyThread, .feed:
            updatedButtons = []
        }
        
        var buttonsUpdated = false
        if self.buttons.count != updatedButtons.count {
            buttonsUpdated = true
        } else {
            for i in 0 ..< updatedButtons.count {
                if self.buttons[i].0 != updatedButtons[i] {
                    buttonsUpdated = true
                    break
                }
            }
        }
        
        if buttonsUpdated || themeUpdated {
            for (_, buttonNode) in self.buttons {
                buttonNode.removeFromSupernode()
            }
            self.buttons.removeAll()
            for button in updatedButtons {
                let buttonNode = ChatInfoTitlePanelButtonNode()
                buttonNode.laysOutHorizontally = false
                
                buttonNode.setup(text: button.title(interfaceState.strings), color: interfaceState.theme.chat.inputPanel.panelControlAccentColor, icon: button.icon(interfaceState.theme))
                
                buttonNode.addTarget(self, action: #selector(self.buttonPressed(_:)), forControlEvents: [.touchUpInside])
                self.addSubnode(buttonNode)
                self.buttons.append((button, buttonNode))
            }
        }
        
        if !self.buttons.isEmpty {
            let buttonWidth = floor((width - leftInset - rightInset) / CGFloat(self.buttons.count))
            var nextButtonOrigin: CGFloat = leftInset
            for (_, buttonNode) in self.buttons {
                buttonNode.frame = CGRect(origin: CGPoint(x: nextButtonOrigin, y: 0.0), size: CGSize(width: buttonWidth, height: panelHeight))
                nextButtonOrigin += buttonWidth
            }
        }
        
        transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: UIScreenPixel)))
        
        return LayoutResult(backgroundHeight: panelHeight, insetHeight: panelHeight)
    }
    
    @objc func buttonPressed(_ node: HighlightableButtonNode) {
        for (button, buttonNode) in self.buttons {
            if buttonNode === node {
                switch button {
                    case .info:
                        self.interfaceInteraction?.openPeerInfo()
                    case .mute:
                        self.interfaceInteraction?.togglePeerNotifications()
                    case .unmute:
                        self.interfaceInteraction?.togglePeerNotifications()
                    case .search:
                        self.interfaceInteraction?.beginMessageSearch(.everything, "")
                    case .call:
                        self.interfaceInteraction?.beginCall(false)
                    case .report:
                        self.interfaceInteraction?.reportPeer()
                    case .unarchive:
                        self.interfaceInteraction?.unarchiveChat()
                }
                break
            }
        }
    }
}