import Foundation
import BlazeSDK

extension BlazeWidgetLayout {
    func mergedWith(_ customization: BlazeReactWidgetLayout?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.horizontalItemsSpacing = customization.horizontalItemsSpacing ?? merged.horizontalItemsSpacing
        merged.verticalItemsSpacing = customization.verticalItemsSpacing ?? merged.verticalItemsSpacing
        merged.itemRatio = customization.itemRatio ?? merged.itemRatio
        merged.columns = customization.columns ?? merged.columns
        merged.maxDisplayItemsCount = customization.maxDisplayItemsCount ?? merged.maxDisplayItemsCount
        merged.widgetItemStyle = merged.widgetItemStyle.mergedWith(customization.widgetItemStyle)
        merged.margins = merged.margins.mergedWith(customization.margins)
        return merged
    }
}

extension BlazeStoryPlayerStyle {
    func mergedWith(_ customization: BlazeReactStoryPlayerStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.title = merged.title.mergedWith(customization.title)
        merged.lastUpdate = merged.lastUpdate.mergedWith(customization.lastUpdate)
        merged.buttons = merged.buttons.mergedWith(customization.buttons)
        merged.chips = merged.chips.mergedWith(customization.chips)
        merged.backgroundColor = UIColor(hexString: customization.backgroundColor) ?? merged.backgroundColor
        merged.cta = merged.cta.mergedWith(customization.cta)
        merged.headerGradient = merged.headerGradient.mergedWith(customization.headerGradient)
        merged.firstTimeSlide = merged.firstTimeSlide.mergedWith(customization.firstTimeSlide)
        merged.progressBar = merged.progressBar.mergedWith(customization.progressBar)

        return merged
    }
}

extension BlazeStoryPlayerProgressBarStyle {
    func mergedWith(_ customization: BlazeReactStoryPlayerProgressBarStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.backgroundColor = UIColor(hexString: customization.backgroundColor) ?? merged.backgroundColor
        merged.progressColor = UIColor(hexString: customization.progressColor) ?? merged.progressColor
        return merged
    }
}

extension BlazeStoryPlayerFirstTimeSlideStyle {
    func mergedWith(_ customization: BlazeReactStoryPlayerFirstTimeSlideStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.backgroundColor = UIColor(hexString: customization.backgroundColor?.colorName) ?? merged.backgroundColor
        merged.show = customization.show ?? merged.show
        merged.mainTitle = merged.mainTitle.mergedWith(customization.mainTitle)
        merged.cta = merged.cta.mergedWith(customization.cta)
        merged.subtitle = merged.subtitle.mergedWith(customization.subtitle)
        merged.instructions = merged.instructions.mergedWith(customization.instructions)
        return merged
    }
}

extension BlazeStoryPlayerFirstTimeSlideInstructionsStyle {
    func mergedWith(_ customization: BlazeReactStoryPlayerFirstTimeSlideInstructionsStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.backward = merged.backward.mergedWith(customization.backward)
        merged.forward = merged.forward.mergedWith(customization.forward)
        merged.pause = merged.pause.mergedWith(customization.pause)
        merged.transition = merged.transition.mergedWith(customization.transition)
        return merged
    }
}

extension BlazeFirstTimeSlideInstructionStyle {
    func mergedWith(_ customization: BlazeReactFirstTimeSlideInstructionStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.descriptionText = merged.descriptionText.mergedWith(customization.descriptionText)
        merged.headerText = merged.headerText.mergedWith(customization.headerText)
        return merged
    }
}

extension BlazeFirstTimeSlideCTAStyle {
    func mergedWith(_ customization: BlazeReactFirstTimeSlideCTAStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.backgroundColor = UIColor(hexString: customization.backgroundColor?.colorName
        ) ?? merged.backgroundColor
        merged.cornerRadius = customization.cornerRadius ?? merged.cornerRadius
        merged.textColor = UIColor(hexString: customization.textColor?.colorName) ?? merged.textColor
        merged.font = merged.font.fontWith(customization.font, textSize: customization.textSize)
        merged.title = customization.title ?? merged.title
        return merged
    }
}

extension BlazeFirstTimeSlideTextStyle {
    func mergedWith(_ customization: BlazeReactFirstTimeSlideTextStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.textColor = UIColor(hexString: customization.textColor?.colorName) ?? merged.textColor
        merged.font = merged.font.fontWith(customization.font, textSize: customization.textSize)
        merged.text = customization.text ?? merged.text
        
        return merged
    }
}

extension BlazeStoryPlayerHeaderGradientStyle {
    func mergedWith(_ customization: BlazeReactStoryPlayerHeaderGradientStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.startColor = UIColor(hexString: customization.startColor) ?? merged.startColor
        merged.endColor = UIColor(hexString: customization.endColor) ?? merged.endColor
        return merged
    }
}

extension BlazeStoryPlayerCtaStyle {
    func mergedWith(_ customization: BlazeReactStoryPlayerCtaStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.cornerRadius = customization.cornerRadius ?? merged.cornerRadius
        merged.font = merged.font.fontWith(customization.font, textSize: customization.textSize)
        return merged
    }
}

extension BlazeStoryPlayerChipsStyle {
    func mergedWith(_ customization: BlazeReactStoryPlayerChipsStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.live = merged.live.mergedWith(customization.live)
        merged.ad = merged.live.mergedWith(customization.ad)
        return merged
    }
}

extension BlazeStoryPlayerChipStyle {
    func mergedWith(_ customization: BlazeReactStoryPlayerChipStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.titlePadding = merged.titlePadding.mergedWith(customization.titlePadding)
        merged.text = customization.text ?? merged.text
        merged.textColor = UIColor(hexString: customization.textColor) ?? merged.textColor
        merged.backgroundColor = UIColor(hexString: customization.backgroundColor) ?? merged.backgroundColor
        merged.isVisible = customization.isVisible ?? merged.isVisible

        return merged
    }
}

extension BlazeStoryPlayerButtonsStyle {
    func mergedWith(_ customization: BlazeReactStoryPlayerButtonsStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.mute = merged.mute.mergedWith(customization.mute)
        merged.exit = merged.exit.mergedWith(customization.exit)
        merged.share = merged.share.mergedWith(customization.share)
        return merged
    }
}

extension BlazeStoryPlayerButtonStyle {
    func mergedWith(_ customization: BlazeReactStoryPlayerButtonStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.width = customization.width ?? merged.width
        merged.height = customization.height ?? merged.height
        merged.color = UIColor(hexString: customization.color) ?? merged.color
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.isVisibleForAds = customization.isVisibleForAds ?? merged.isVisibleForAds
        merged.customImage = merged.customImage.mergedWith(customization.customImage)
        merged.contentHorizontalAlignment = .center
        merged.contentVerticalAlignment = .center

        return merged
    }
}

extension BlazeSDK.BlazeStoryPlayerButtonCustomImageStates? {
    
    func mergedWith(_ customization: BlazeReactPlayerButtonCustomImageStates?) -> Self {
        guard let customization else { return self }
        
        guard let defaultImage = UIImage.imageWith(customization.unselectedImage) else { return self }
        
        return .init(default: defaultImage,
                     selected: UIImage.imageWith(customization.selectedImage))
    }
    
}

extension BlazeSDK.BlazeMomentsPlayerButtonCustomImageStates? {
    
    func mergedWith(_ customization: BlazeReactPlayerButtonCustomImageStates?) -> Self {
        guard let customization else { return self }
        
        guard let defaultImage = UIImage.imageWith(customization.unselectedImage) else { return self }
        
        return .init(default: defaultImage,
                     selected: UIImage.imageWith(customization.selectedImage))
    }
    
}

extension BlazeStoryPlayerTitleTextStyle{
    func mergedWith(_ customization: BlazeReactStoryPlayerTitleTextStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.font = merged.font.fontWith(customization.font, textSize: customization.textSize)
        merged.textColor = UIColor(hexString: customization.textColor) ?? merged.textColor
        merged.isVisible = customization.isVisible ?? merged.isVisible
        return merged
    }
}

extension BlazeStoryPlayerLastUpdateTextStyle{
    func mergedWith(_ customization: BlazeReactStoryPlayerLastUpdateTextStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.font = merged.font.fontWith(customization.font, textSize: customization.textSize)
        merged.textColor = UIColor(hexString: customization.textColor) ?? merged.textColor
        merged.textCase = merged.textCase.mergedWith(customization.textCase)
        merged.isVisible = customization.isVisible ?? merged.isVisible
        return merged
    }
}

extension BlazeTextCase {
    func mergedWith(_ customization: BlazeReactTextCase?) -> Self {
        guard let customization else { return self }
        
        switch customization {
        case .uppercase:
            return .uppercase
        case .lowercase:
            return .lowercase
        }
    }
}

extension BlazeWidgetItemStyle {
    func mergedWith(_ customization: BlazeReactWidgetItemStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.title = merged.title.mergedWith(customization.title)
        merged.image = merged.image.mergedWith(customization.image)
        merged.backgroundColor = UIColor(hexString: customization.backgroundColor) ?? merged.backgroundColor
        merged.cornerRadius = customization.cornerRadius ?? merged.cornerRadius
        merged.cornerRadiusRatio = customization.cornerRadiusRatio ?? merged.cornerRadiusRatio
        merged.insets = merged.insets.mergedWith(customization.margins)
        merged.statusIndicator = merged.statusIndicator.mergedWith(customization.statusIndicator)
        merged.badge = merged.badge.mergedWith(customization.badge)
        
        return merged
    }
}

extension BlazeWidgetItemTitleStyle {
    func mergedWith(_ customization: BlazeReactWidgetItemTitleStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.readState = merged.readState.mergedWith(customization.readState)
        merged.unreadState = merged.unreadState.mergedWith(customization.unreadState)
        merged.position = merged.position.mergedWith(customization.position)
        merged.insets = merged.insets.mergedWith(customization.margins)
        return merged
    }
}

extension BlazeObjectPositioning {
    func mergedWith(_ customization: BlazeReactObjectPositioning?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.xPosition = merged.xPosition.mergedWith(customization.xPosition)
        merged.yPosition = merged.yPosition.mergedWith(customization.yPosition)

        return merged
    }
}

extension BlazeObjectXPosition {
    func mergedWith(_ customization: BlazeReactObjectXPosition?) -> Self {
        guard let customization else { return self }
        var results = BlazeSDK.BlazeObjectXPosition.centerX(offset: 0)
        
        switch customization {
        case .leadingToLeading:
            results = BlazeSDK.BlazeObjectXPosition.leadingToLeading(offset: 0)
        case .leadingToTrailing:
            results = BlazeSDK.BlazeObjectXPosition.leadingToTrailing(offset: 0)
        case .trailingToLeading:
            results = BlazeSDK.BlazeObjectXPosition.trailingToLeading(offset: 0)
        case .trailingToTrailing:
            results = BlazeSDK.BlazeObjectXPosition.trailingToTrailing(offset: 0)
        case .centerX:
            results = BlazeSDK.BlazeObjectXPosition.centerX(offset: 0)
        case .centerToLeading:
            results = BlazeSDK.BlazeObjectXPosition.centerToLeading(offset: 0)
        case .centerToTrailing:
            results = BlazeSDK.BlazeObjectXPosition.centerToTrailing(offset: 0)
        }
        
        return results
    }
}


extension BlazeObjectYPosition {
    func mergedWith(_ customization: BlazeReactObjectYPosition?) -> Self {
        guard let customization else { return self }
        var results = BlazeSDK.BlazeObjectYPosition.centerY(offset: 0)
        
        switch customization {
        case .topToBottom:
            results = BlazeSDK.BlazeObjectYPosition.topToBottom(offset: 0)
        case .bottomToBottom:
            results = BlazeSDK.BlazeObjectYPosition.topToBottom(offset: 0)
        case .bottomToTop:
            results = BlazeSDK.BlazeObjectYPosition.bottomToTop(offset: 0)
        case .centerToTop:
            results = BlazeSDK.BlazeObjectYPosition.centerToTop(offset: 0)
        case .centerY:
            results = BlazeSDK.BlazeObjectYPosition.centerY(offset: 0)
        case .centerToBottom:
            results = BlazeSDK.BlazeObjectYPosition.centerToBottom(offset: 0)
        case .topToTop:
            results = BlazeSDK.BlazeObjectYPosition.topToTop(offset: 0)
        }
        
        return results
    }
}

extension BlazeWidgetItemTextStyle {
    func mergedWith(_ customization: BlazeReactTitleStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.font = merged.font.fontWith(customization.font,
                                           textSize: customization.textSize)
        merged.letterSpacing = customization.letterSpacing ?? merged.letterSpacing
        merged.textColor = UIColor(hexString: customization.textColor) ?? merged.textColor
        merged.lineHeight = customization.lineHeight ?? merged.lineHeight
        merged.numberOfLines = customization.maxLines ?? merged.numberOfLines
        merged.alignment = merged.alignment.mergedWith(customization.textAlign)
        
        return merged
    }
}

extension BlazeWidgetItemImageStyle {
    func mergedWith(_ customization: BlazeReactWidgetItemImageStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.position = merged.position.mergedWith(customization.position)
        merged.width = customization.width ?? merged.width
        merged.height = customization.height ?? merged.height
        merged.ratio = customization.ratio ?? merged.ratio
        merged.cornerRadius = customization.cornerRadius ?? merged.cornerRadius
        merged.cornerRadiusRatio = customization.cornerRadiusRatio ?? merged.cornerRadiusRatio
        merged.border = merged.border.mergedWith(customization.border)
        merged.thumbnailType = merged.thumbnailType.mergedWith(customization.thumbnailType)
        merged.insets = merged.insets.mergedWith(customization.margins)
        merged.animatedThumbnail = merged.animatedThumbnail.mergedWith(customization.animatedThumbnail)
        merged.gradientOverlay = merged.gradientOverlay.mergedWith(customization.gradientOverlay)
        
        return merged
    }
}

extension BlazeSDK.BlazeWidgetItemImageGradientOverlayStyle {
    
    func mergedWith(_ customization: BlazeReactWidgetItemImageGradientOverlayStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.position = merged.position.mergedWith(customization.position)
        merged.startColor = UIColor(hexString: customization.startColor) ?? merged.startColor
        merged.endColor = UIColor(hexString: customization.endColor) ?? merged.endColor
        
        return merged
    }
}

extension BlazeSDK.BlazeWidgetItemImageGradientOverlayStyle.Position {
    func mergedWith(_ customization: BlazeReactWidgetItemImageGradientOverlayStyle.Position?) -> Self {
        guard let customization else { return self }
        
        let result: Self
        switch customization {
        case .top:
            result = .top
        case .center:
            result = .center
        case .bottom:
            result = .bottom
        }
        
        return result
    }
}

extension BlazeWidgetItemImageAnimatedThumbnailStyle {
    func mergedWith(_ customization: BlazeReactWidgetItemAnimatedThumbnailStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.horizontalAnimationTriggerPercentage = customization.horizontalAnimationTriggerPercentage ?? merged.horizontalAnimationTriggerPercentage
        merged.isEnabled = customization.isEnabled ?? merged.isEnabled
        
        return merged
    }
}

extension BlazeWidgetItemImageStyle.Position {
    func mergedWith(_ customization: BlazeReactWidgetItemImagePosition?) -> Self {
        guard let customization else { return self }
        
        let result: Self
        switch customization {
        case .topStart:
            result = .topLeading
        case .topCenter:
            result = .topCenter
        case .topEnd:
            result = .topTrailing
        case .centerStart:
            result = .centerLeading
        case .center:
            result = .center
        case .centerEnd:
            result = .centerTrailing
        case .bottomStart:
            result = .bottomLeading
        case .bottomCenter:
            result = .bottomCenter
        case .bottomEnd:
            result = .bottomTrailing
        }
        
        return result
    }
}

extension BlazeWidgetItemImageContainerBorderStyle {
    func mergedWith(_ customization: BlazeReactWidgetItemImageContainerBorderStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.liveReadState = merged.liveReadState.mergedWith(customization.liveReadState)
        merged.liveUnreadState = merged.liveUnreadState.mergedWith(customization.liveUnreadState)
        merged.readState = merged.readState.mergedWith(customization.readState)
        merged.unreadState = merged.unreadState.mergedWith(customization.unreadState)
        
        return merged
    }
}

extension BlazeWidgetItemBadgeStyle {
    func mergedWith(_ customization: BlazeReactWidgetItemBadgeStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.position = merged.position.mergedWith(customization.position)
        merged.insets = merged.insets.mergedWith(customization.margins)
        merged.liveUnreadState = merged.liveUnreadState.mergedWith(customization.liveUnreadState)
        merged.liveReadState = merged.liveReadState.mergedWith(customization.liveReadState)
        merged.unreadState = merged.unreadState.mergedWith(customization.unreadState)
        merged.readState = merged.readState.mergedWith(customization.readState)
        
        return merged
    }
}

extension BlazeWidgetItemBadgeStateStyle {
    func mergedWith(_ customization: BlazeReactWidgetItemBadgeStateStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.backgroundColor = UIColor(hexString: customization.backgroundColor) ?? merged.backgroundColor
        merged.backgroundImage = UIImage.imageWith(customization.backgroundImage) ?? merged.backgroundImage
        merged.textStyle = merged.textStyle.mergedWith(customization.textStyle)
        merged.text = customization.text ?? merged.text
        merged.cornerRadius = customization.cornerRadius ?? merged.cornerRadius
        merged.cornerRadiusRatio = customization.cornerRadiusRatio ?? merged.cornerRadiusRatio
        merged.borderColor = UIColor(hexString: customization.borderColor) ?? merged.borderColor
        merged.borderWidth = customization.borderWidth ?? merged.borderWidth
        merged.width = customization.width ?? merged.width
        merged.height = customization.height ?? merged.height
        
        return merged
    }
}

extension BlazeWidgetItemStatusIndicatorStyle {
    func mergedWith(_ customization: BlazeReactWidgetItemStatusIndicatorStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.position = merged.position.mergedWith(customization.position)
        merged.insets = merged.insets.mergedWith(customization.margins)
        merged.statusTitlePadding = merged.statusTitlePadding.mergedWith(customization.statusTitlePadding)
        merged.liveUnreadState = merged.liveUnreadState.mergedWith(customization.liveUnreadState)
        merged.liveReadState = merged.liveReadState.mergedWith(customization.liveReadState)
        merged.unreadState = merged.unreadState.mergedWith(customization.unreadState)
        merged.readState = merged.readState.mergedWith(customization.readState)
        
        return merged
    }
}

extension BlazeWidgetItemStatusIndicatorStateStyle {
    func mergedWith(_ customization: BlazeReactWidgetItemStatusIndicatorStateStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.backgroundColor = UIColor(hexString: customization.backgroundColor) ?? merged.backgroundColor
        merged.backgroundImage = UIImage.imageWith(customization.backgroundImage) ?? merged.backgroundImage
        merged.textStyle = merged.textStyle.mergedWith(customization.textStyle)
        merged.text = customization.text ?? merged.text
        merged.cornerRadius = customization.cornerRadius ?? merged.cornerRadius
        merged.cornerRadiusRatio = customization.cornerRadiusRatio ?? merged.cornerRadiusRatio
        merged.borderColor = UIColor(hexString: customization.borderColor) ?? merged.borderColor
        merged.borderWidth = customization.borderWidth ?? merged.borderWidth
        
        return merged
    }
}

extension BlazeWidgetItemImageContainerBorderStateStyle {
    func mergedWith(_ customization: BlazeReactWidgetItemImageContainerBorderStateStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.color = UIColor(hexString: customization.color) ?? merged.color
        merged.insets = customization.margin ?? merged.insets
        merged.width = customization.width ?? merged.width
        
        return merged
    }
}

extension BlazeWidgetItemImageStyle.ThumbnailType {
    func mergedWith(_ customization: BlazeReactThumbnailType?) -> Self {
        guard let customization else { return self }
        
        let result: BlazeWidgetItemImageStyle.ThumbnailType
        switch customization {
        case .squareIcon:
            result = .squareIcon
        case .verticalTwoByThree:
            result = .verticalTwoByThree
        case .custom:
            result = .custom
        }
        
        return result
    }
}

extension BlazeWidgetItemStyleOverrides {
    func mergedWith(_ customization: BlazeReactWidgetStylesOverrides?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.statusIndicator = merged.statusIndicator?.mergedWith(customization.statusIndicator)
        merged.imageBorder = merged.imageBorder?.mergedWith(customization.imageBorder)
        merged.badge = merged.badge?.mergedWith(customization.badge)
        
        return merged
    }
}



///
/// Moments
///
extension BlazeMomentsPlayerStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.headingText = merged.headingText.mergedWith(customization.headingText)
        merged.bodyText = merged.bodyText.mergedWith(customization.bodyText)
        merged.buttons = merged.buttons.mergedWith(customization.buttons)
        merged.chips = merged.chips.mergedWith(customization.chips)
        merged.cta = merged.cta.mergedWith(customization.cta)
        merged.headerGradient = merged.headerGradient.mergedWith(customization.headerGradient)
        merged.footerGradient = merged.footerGradient.mergedWith(customization.footerGradient)
        merged.backgroundColor = UIColor(hexString: customization.backgroundColor) ?? merged.backgroundColor
        merged.firstTimeSlide = merged.firstTimeSlide.mergedWith(customization.firstTimeSlide)
        merged.seekBar = merged.seekBar.mergedWith(customization.seekBar)
        merged.bottomComponentsAlignment = merged.bottomComponentsAlignment.mergedWith(customization.bottomComponentsAlignment)
        merged.playerDisplayMode = merged.playerDisplayMode.mergedWith(customization.playerDisplayMode)
        return merged
    }
}

extension BlazeMomentsPlayerSeekBarStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerSeekBarStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.playingState = merged.playingState.mergedWith(customization.playingState)
        merged.pausedState = merged.pausedState.mergedWith(customization.pausedState)
        merged.horizontalSpacing = customization.horizontalSpacing ?? merged.horizontalSpacing
        merged.bottomSpacing = customization.bottomSpacing ?? merged.bottomSpacing
        return merged
    }
}

extension BlazeSeekBarStyle {
    func mergedWith(_ customization: BlazeReactSeekBarStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.backgroundColor = UIColor(hexString: customization.backgroundColor) ?? merged.backgroundColor
        merged.progressColor = UIColor(hexString: customization.progressColor) ?? merged.progressColor
        merged.height = customization.height ?? merged.height        
        merged.cornerRadius = customization.cornerRadius ?? merged.cornerRadius
        merged.thumbColor = UIColor(hexString: customization.thumbColor) ?? merged.thumbColor
        merged.thumbImage = UIImage.imageWith(customization.thumbImage) ?? merged.thumbImage
        merged.thumbSize = customization.thumbSize ?? merged.thumbSize
        merged.isThumbVisible = customization.isThumbVisible ?? merged.isThumbVisible
        return merged
    }
}

extension BlazeMomentsPlayerFirstTimeSlideInstructionsStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerFirstTimeSlideInstructionsStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.next = merged.next.mergedWith(customization.next)
        merged.pause = merged.pause.mergedWith(customization.pause)
        merged.play = merged.play.mergedWith(customization.play)
        merged.previous = merged.previous.mergedWith(customization.previous)
        return merged
    }
}

extension BlazeMomentsPlayerFirstTimeSlideStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerFirstTimeSlideStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.backgroundColor = UIColor(hexString: customization.backgroundColor?.colorName) ?? merged.backgroundColor
        merged.show = customization.show ?? merged.show
        merged.mainTitle = merged.mainTitle.mergedWith(customization.mainTitle)
        merged.cta = merged.cta.mergedWith(customization.cta)
        merged.subtitle = merged.subtitle.mergedWith(customization.subtitle)
        merged.instructions = merged.instructions.mergedWith(customization.instructions)
        return merged
    }
}


extension BlazeMomentsPlayerHeaderGradientStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerHeaderGradientStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.startColor = UIColor(hexString: customization.startColor) ?? merged.startColor
        merged.endColor = UIColor(hexString: customization.endColor) ?? merged.endColor
        return merged
    }
}

extension BlazeMomentsPlayerFooterGradientStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerFooterGradientStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.startColor = UIColor(hexString: customization.startColor) ?? merged.startColor
        merged.endColor = UIColor(hexString: customization.endColor) ?? merged.endColor
        merged.endPositioning = merged.endPositioning.mergedWith(customization.endPositioning)
        return merged
    }
}

extension BlazeMomentsPlayerFooterGradientStyle.EndPositioning {
    
    func mergedWith(_ customization: BlazeReactMomentsPlayerFooterGradientStyle.EndPositioning?) -> Self {
        guard let customization else { return self }
        
        switch customization {
        case .bottomToContainer:
            return .bottomToContainer
        case .bottomToPlayer:
            return .bottomToPlayer
        }
    }
    
}

extension BlazeMomentsPlayerCtaStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerCtaStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.cornerRadius = customization.cornerRadius ?? merged.cornerRadius
        merged.height = customization.height ?? merged.height
        merged.width = customization.width ?? merged.width
        merged.font = merged.font.fontWith(customization.font, textSize: customization.textSize)
        merged.layoutPositioning = merged.layoutPositioning.mergedWith(customization.layoutPositioning)
        merged.horizontalAlignment = merged.horizontalAlignment.mergedWith(customization.horizontalAlignment)
        merged.icon = UIImage.imageWith(customization.icon?.iconImage)
        return merged
    }
}

extension BlazeMomentsPlayerCtaStyle.CTAPositioning {
    func mergedWith(_ customization: BlazeReactMomentsPlayerCtaStyle.CTAPositioning?) -> Self {
        guard let customization else { return self }
        
        switch customization {
        case .bellowBottomButtonsBox:
            return .ctaBellowBottomButtonsBox
        case .nextToBottomButtonsBox:
            return .ctaNextToBottomButtonsBox
        }
        
    }
}

extension BlazeMomentsPlayerCtaStyle.CTAHorizontalAlignment {
    func mergedWith(_ customization: BlazeReactMomentsPlayerCtaStyle.CTAHorizontalAlignment?) -> Self {
        guard let customization else { return self }
        
        switch customization {
        case .start:
            return .leading
        case .center:
            return .center
        case .end:
            return .trailing
        case .fullAvailableWidth:
            return .fullAvailableWidth
        }
    }
}

extension BlazeMomentsPlayerChipsStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerChipsStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.ad = merged.ad.mergedWith(customization.ad)
        return merged
    }
}

extension BlazeMomentsPlayerChipStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerChipStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.backgroundColor = UIColor(hexString: customization.backgroundColor) ?? merged.backgroundColor
        merged.text = customization.text ?? merged.text
        merged.textColor = UIColor(hexString: customization.textColor) ?? merged.textColor
        merged.titlePadding = merged.titlePadding.mergedWith(customization.titlePadding)
        merged.isVisible = customization.isVisible ?? merged.isVisible
        return merged
    }
}

extension BlazeMomentsPlayerButtonsStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerButtonsStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.exit = merged.exit.mergedWith(customization.exit)
        merged.like = merged.like.mergedWith(customization.like)
        merged.mute = merged.mute.mergedWith(customization.mute)
        merged.play = merged.play.mergedWith(customization.play)
        merged.share = merged.share.mergedWith(customization.share)
        return merged
    }
}

extension BlazeMomentsPlayerButtonStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerButtonStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        merged.color = UIColor(hexString: customization.color) ?? merged.color
        merged.height = customization.height ?? merged.height
        merged.width = customization.width ?? merged.width
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.isVisibleForAds = customization.isVisibleForAds ?? merged.isVisibleForAds
        merged.customImage = merged.customImage.mergedWith(customization.customImage)
        merged.contentHorizontalAlignment = .center
        merged.contentVerticalAlignment = .center

        return merged
    }
}

extension BlazeMomentsPlayerHeadingTextStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerHeadingTextStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.textColor = UIColor(hexString: customization.textColor) ?? merged.textColor
        merged.font = merged.font.fontWith(customization.font, textSize: customization.textSize)
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.contentSource = merged.contentSource.mergedWith(customization.contentSource)
        
        return merged
    }
}

extension BlazeMomentsPlayerBodyTextStyle {
    func mergedWith(_ customization: BlazeReactMomentsPlayerBodyTextStyle?) -> Self {
        guard let customization else { return self }
        
        var merged = self
        
        merged.textColor = UIColor(hexString: customization.textColor) ?? merged.textColor
        merged.font = merged.font.fontWith(customization.font, textSize: customization.textSize)
        merged.isVisible = customization.isVisible ?? merged.isVisible
        merged.contentSource = merged.contentSource.mergedWith(customization.contentSource)
        
        return merged
    }
}

extension BlazeMomentsPlayerHeadingTextStyle.ContentSource {
    
    func mergedWith(_ customization: BlazeReactMomentsPlayerHeadingTextStyle.ContentSource?) -> Self {
        guard let customization else { return self }
        
        switch customization {
        case .title:
            return .title
        case .subtitle:
            return .subtitle
        }
    }
    
}

extension BlazeMomentsPlayerBodyTextStyle.ContentSource {
    
    func mergedWith(_ customization: BlazeReactMomentsPlayerBodyTextStyle.ContentSource?) -> Self {
        guard let customization else { return self }
        
        switch customization {
        case .title:
            return .title
        case .subtitle:
            return .subtitle
        case .description:
            return .description
        }
    }
    
}
extension BlazeMomentsPlayerStyle.BottomComponentsAlignment {
    
    func mergedWith(_ customization: BlazeReactBottomComponentsAlignment?) -> Self {
        guard let customization else { return self }
        
        switch customization {
        case .relativeToContainer:
            return .relativeToContainer
        case .relativeToPlayer:
            return .relativeToPlayer
        case .fitCtaBelowPlayer:
            return .fitCTABelowPlayer
        }
    }
    
}

extension BlazePlayerDisplayMode {
    
    func mergedWith(_ customization: BlazeReactPlayerDisplayMode?) -> Self {
        guard let customization else { return self }
        
        switch customization {
        case .fixedRatio_9_16:
            return .fixedRatio_9_16
        case .resizeAspectFillCenterCrop:
            return .resizeAspectFillCenterCrop
        }
    }
}



///
/// UI
///
extension NSTextAlignment {
    func mergedWith(_ customization: BlazeReactTextAlign?) -> Self {
        guard let customization else { return self }
        
        let result: NSTextAlignment
        switch customization {
            
        case .start:
            result = .left
        case .center:
            result = .center
        case .end:
            result = .right
        }
        
        return result
    }
}

extension NSDirectionalEdgeInsets {
    func mergedWith(_ customization: BlazeReactMargins?) -> Self {
        guard let customization else { return self }

        let result = NSDirectionalEdgeInsets(top: customization.top ?? top, leading: customization.leading ?? leading, bottom: customization.bottom ?? bottom, trailing: customization.trailing ?? trailing)

        return result
    }
}

extension UIFont {
    func fontWith(_ customization: BlazeReactTitleFont?,
                  textSize: CGFloat?) -> UIFont {
        var size = pointSize // Default size is current size.
        if let textSize {
            size = textSize
        }
        
        guard let fontName = customization?.fontName else {
            return self.withSize(size)
        }
        
        return UIFont(name: fontName, size: size) ?? self
    }
}

extension UIImage {
    
    static func imageWith(_ customization: BlazeReactImage?) -> UIImage? {
        guard let imageName = customization?.imageName else { return nil }
        
        return UIImage(named: imageName)
    }
    
}
