import Foundation
import UIKit
import Display
import AsyncDisplayKit
import SwiftSignalKit
import TelegramPresentationData
import AccountContext
import ContextUI
import TelegramCore
import TextFormat
import ReactionSelectionNode
import ViewControllerComponent
import ComponentFlow
import ComponentDisplayAdapters
import ChatMessageBackground
import WallpaperBackgroundNode
import AppBundle
import ActivityIndicator
import RadialStatusNode

final class SendButton: HighlightTrackingButton {
    enum Kind {
        case send
        case edit
    }
    
    private let kind: Kind
    
    private let containerView: UIView
    private var backgroundContent: WallpaperBubbleBackgroundNode?
    private let backgroundLayer: SimpleLayer
    private let iconView: UIImageView
    private var activityIndicator: RadialStatusNode?
    
    private var previousIsAnimatedIn: Bool?
    private var sourceCustomContentView: UIView?
    
    init(kind: Kind) {
        self.kind = kind
        
        self.containerView = UIView()
        self.containerView.isUserInteractionEnabled = false
        
        self.backgroundLayer = SimpleLayer()
        
        self.iconView = UIImageView()
        self.iconView.isUserInteractionEnabled = false
        
        super.init(frame: CGRect())
        
        self.containerView.clipsToBounds = true
        self.addSubview(self.containerView)
        
        self.containerView.layer.addSublayer(self.backgroundLayer)
        self.containerView.addSubview(self.iconView)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func update(
        context: AccountContext,
        presentationData: PresentationData,
        backgroundNode: WallpaperBackgroundNode?,
        sourceSendButton: ASDisplayNode,
        isAnimatedIn: Bool,
        isLoadingEffectAnimation: Bool,
        size: CGSize,
        transition: ComponentTransition
    ) {
        let innerSize = CGSize(width: size.width - 5.5 * 2.0, height: 33.0)
        let containerFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - innerSize.width) * 0.5), y: floorToScreenPixels((size.height - innerSize.height) * 0.5)), size: innerSize)
        transition.setFrame(view: self.containerView, frame: containerFrame)
        transition.setCornerRadius(layer: self.containerView.layer, cornerRadius: innerSize.height * 0.5)
        
        if self.window != nil {
            if self.backgroundContent == nil, let backgroundNode = backgroundNode as? WallpaperBackgroundNodeImpl {
                if let backgroundContent = backgroundNode.makeLegacyBubbleBackground(for: .outgoing) {
                    self.backgroundContent = backgroundContent
                    self.containerView.insertSubview(backgroundContent.view, at: 0)
                }
            }
        }
        
        if let backgroundContent = self.backgroundContent {
            transition.setFrame(view: backgroundContent.view, frame: CGRect(origin: CGPoint(), size: innerSize))
        }
        
        if backgroundNode != nil && [.day, .night].contains(presentationData.theme.referenceTheme.baseTheme) && !presentationData.theme.chat.message.outgoing.bubble.withWallpaper.hasSingleFillColor {
            self.backgroundContent?.isHidden = false
            self.backgroundLayer.isHidden = true
        } else {
            self.backgroundContent?.isHidden = true
            self.backgroundLayer.isHidden = false
        }
        
        self.backgroundLayer.backgroundColor = presentationData.theme.chat.inputPanel.actionControlFillColor.cgColor
        transition.setFrame(layer: self.backgroundLayer, frame: CGRect(origin: CGPoint(), size: innerSize))
        
        if self.previousIsAnimatedIn != isAnimatedIn {
            self.previousIsAnimatedIn = isAnimatedIn
            
            var sourceCustomContentViewAlpha: CGFloat = 1.0
            if let sourceCustomContentView = self.sourceCustomContentView {
                sourceCustomContentViewAlpha = sourceCustomContentView.alpha
                sourceCustomContentView.removeFromSuperview()
                self.sourceCustomContentView = nil
            }
            
            if let sourceSendButton = sourceSendButton as? ChatSendMessageActionSheetControllerSourceSendButtonNode {
                if let sourceCustomContentView = sourceSendButton.makeCustomContents() {
                    self.sourceCustomContentView = sourceCustomContentView
                    sourceCustomContentView.alpha = sourceCustomContentViewAlpha
                    self.addSubview(sourceCustomContentView)
                }
            }
        }
        
        if self.iconView.image == nil {
            switch self.kind {
            case .send:
                self.iconView.image = PresentationResourcesChat.chatInputPanelSendIconImage(presentationData.theme)
            case .edit:
                self.iconView.image = PresentationResourcesChat.chatInputPanelApplyIconImage(presentationData.theme)
            }
        }
        
        if let sourceCustomContentView = self.sourceCustomContentView {
            var sourceCustomContentTransition = transition
            if sourceCustomContentView.bounds.isEmpty {
                sourceCustomContentTransition = .immediate
            }
            
            let sourceCustomContentSize = sourceCustomContentView.bounds.size
            let sourceCustomContentFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((innerSize.width - sourceCustomContentSize.width) * 0.5) + UIScreenPixel, y: floorToScreenPixels((innerSize.height - sourceCustomContentSize.height) * 0.5)), size: sourceCustomContentSize).offsetBy(dx: containerFrame.minX, dy: containerFrame.minY)
            sourceCustomContentTransition.setPosition(view: sourceCustomContentView, position: sourceCustomContentFrame.center)
            sourceCustomContentTransition.setBounds(view: sourceCustomContentView, bounds: CGRect(origin: CGPoint(), size: sourceCustomContentFrame.size))
            sourceCustomContentTransition.setAlpha(view: sourceCustomContentView, alpha: isAnimatedIn ? 0.0 : 1.0)
        }
        
        if let icon = self.iconView.image {
            let iconFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((innerSize.width - icon.size.width) * 0.5) - UIScreenPixel, y: floorToScreenPixels((innerSize.height - icon.size.height) * 0.5)), size: icon.size)
            transition.setPosition(view: self.iconView, position: iconFrame.center)
            transition.setBounds(view: self.iconView, bounds: CGRect(origin: CGPoint(), size: iconFrame.size))
            
            let iconViewAlpha: CGFloat
            if (self.sourceCustomContentView != nil && !isAnimatedIn) || isLoadingEffectAnimation {
                iconViewAlpha = 0.0
            } else {
                iconViewAlpha = 1.0
            }
            transition.setAlpha(view: self.iconView, alpha: iconViewAlpha)
            transition.setScale(view: self.iconView, scale: isLoadingEffectAnimation ? 0.001 : 1.0)
        }
        
        if isLoadingEffectAnimation {
            var animateIn = false
            let activityIndicator: RadialStatusNode
            if let current = self.activityIndicator {
                activityIndicator = current
            } else {
                animateIn = true
                activityIndicator = RadialStatusNode(
                    backgroundNodeColor: .clear,
                    enableBlur: false,
                    isPreview: false
                )
                activityIndicator.transitionToState(.progress(
                    color: presentationData.theme.list.itemCheckColors.foregroundColor,
                    lineWidth: 2.0,
                    value: nil,
                    cancelEnabled: false,
                    animateRotation: true
                ))
                self.activityIndicator = activityIndicator
                self.containerView.addSubview(activityIndicator.view)
            }
            
            let activityIndicatorSize = CGSize(width: 18.0, height: 18.0)
            let activityIndicatorFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((innerSize.width - activityIndicatorSize.width) * 0.5), y: floor((innerSize.height - activityIndicatorSize.height) * 0.5) + UIScreenPixel), size: activityIndicatorSize)
            if animateIn {
                activityIndicator.view.frame = activityIndicatorFrame
                transition.animateAlpha(view: activityIndicator.view, from: 0.0, to: 1.0)
                transition.animateScale(view: activityIndicator.view, from: 0.001, to: 1.0)
            } else {
                transition.setFrame(view: activityIndicator.view, frame: activityIndicatorFrame)
            }
        } else {
            if let activityIndicator = self.activityIndicator {
                self.activityIndicator = nil
                transition.setAlpha(view: activityIndicator.view, alpha: 0.0, completion: { [weak activityIndicator] _ in
                    activityIndicator?.view.removeFromSuperview()
                })
                transition.setScale(view: activityIndicator.view, scale: 0.001)
            }
        }
    }
    
    func updateGlobalRect(rect: CGRect, within containerSize: CGSize, transition: ComponentTransition) {
        if let backgroundContent = self.backgroundContent {
            backgroundContent.update(rect: CGRect(origin: CGPoint(x: rect.minX + self.containerView.frame.minX, y: rect.minY + self.containerView.frame.minY), size: backgroundContent.bounds.size), within: containerSize, transition: transition.containedViewLayoutTransition)
        }
    }
}