/*****************************************************************************
 * VLCLibraryAudioGroupTableHeaderView.m: MacOS X interface module
 *****************************************************************************
 * Copyright (C) 2025 VLC authors and VideoLAN
 *
 * Authors: Claudio Cambra <developer@claudiocambra.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#import "VLCLibraryAudioGroupTableHeaderView.h"

#import "library/VLCLibraryRepresentedItem.h"
#import "library/VLCLibraryUIUnits.h"

#import "extensions/NSColor+VLCAdditions.h"
#import "extensions/NSFont+VLCAdditions.h"
#import "extensions/NSString+Helpers.h"
#import "extensions/NSView+VLCAdditions.h"

const CGFloat VLCLibraryAudioGroupTableHeaderViewHeight = 86.f;
NSString * const VLCLibraryAudioGroupTableHeaderViewIdentifier = @"VLCLibraryAudioGroupTableHeaderView";

@interface VLCLibraryAudioGroupTableHeaderView ()

@property NSView *backgroundView;
@property NSStackView *rootStackView;
@property NSStackView *labelsStackView;
@property NSStackView *buttonsStackView;
@property NSTextField *titleField;
@property NSTextField *detailField;
@property NSButton *playButton;
@property NSButton *queueButton;

@property CGFloat backgroundTopInset;
@property CGFloat backgroundBottomInset;

@end

@implementation VLCLibraryAudioGroupTableHeaderView

- (instancetype)initWithFrame:(NSRect)frameRect
{
    self = [super initWithFrame:frameRect];
    if (self) {
        [self commonInit];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        [self commonInit];
    }
    return self;
}

- (instancetype)initWithFrame:(NSRect)frameRect withInternalPaddingAddedForContentView:(BOOL)internalPaddingAddedForContentView
{
    self = [super initWithFrame:frameRect];
    if (self) {
        _internalPaddingAddedForContentView = internalPaddingAddedForContentView;
        [self commonInit];
    }
    return self;
}

- (void)commonInit
{
    NSView *contentHostView = self;
    self.backgroundTopInset = VLCLibraryUIUnits.largeSpacing + VLCLibraryUIUnits.mediumSpacing;
    self.backgroundBottomInset = 0.f;

#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 260000
    if (@available(macOS 26.0, *)) {
        NSGlassEffectView * const glassView = [[NSGlassEffectView alloc] initWithFrame:self.bounds];
        glassView.translatesAutoresizingMaskIntoConstraints = NO;
        NSView * const glassContentView = [[NSView alloc] initWithFrame:glassView.bounds];
        glassContentView.translatesAutoresizingMaskIntoConstraints = NO;
        glassView.contentView = glassContentView;
        self.backgroundView = glassView;
        contentHostView = glassContentView;
        self.backgroundBottomInset = VLCLibraryUIUnits.largeSpacing + VLCLibraryUIUnits.mediumSpacing + VLCLibraryUIUnits.smallSpacing;
    } else
#endif
    if (@available(macOS 10.14, *)) {
        NSVisualEffectView * const visualEffectView = [[NSVisualEffectView alloc] initWithFrame:self.bounds];
        visualEffectView.translatesAutoresizingMaskIntoConstraints = NO;
        visualEffectView.wantsLayer = YES;
        visualEffectView.material = NSVisualEffectMaterialPopover;
        visualEffectView.blendingMode = NSVisualEffectBlendingModeWithinWindow;
        self.backgroundView = visualEffectView;
        contentHostView = visualEffectView;
    } else {
        NSView * const fallbackBackgroundView = [[NSView alloc] initWithFrame:self.bounds];
        fallbackBackgroundView.translatesAutoresizingMaskIntoConstraints = NO;
        fallbackBackgroundView.wantsLayer = YES;
        fallbackBackgroundView.layer.backgroundColor = NSColor.windowBackgroundColor.CGColor;
        self.backgroundView = fallbackBackgroundView;
        contentHostView = fallbackBackgroundView;
    }

    [self addSubview:self.backgroundView];

    self.titleField = [self buildLabelWithFont:NSFont.VLClibrarySectionHeaderFont
                                      textColor:NSColor.labelColor
                                      alignment:NSTextAlignmentLeft];
    self.detailField = [self buildLabelWithFont:NSFont.VLCLibrarySubsectionSubheaderFont
                                       textColor:NSColor.secondaryLabelColor
                                       alignment:NSTextAlignmentLeft];
    self.playButton = [self buildActionButtonWithTitle:_NS("Play") action:@selector(play:)];
    self.queueButton = [self buildActionButtonWithTitle:_NS("Queue") action:@selector(enqueue:)];

    NSStackView * const labelsStack = [NSStackView stackViewWithViews:@[self.titleField, self.detailField]];
    labelsStack.translatesAutoresizingMaskIntoConstraints = NO;
    labelsStack.orientation = NSUserInterfaceLayoutOrientationVertical;
    labelsStack.alignment = NSLayoutAttributeLeading;
    labelsStack.spacing = VLCLibraryUIUnits.smallSpacing;
    [labelsStack setContentHuggingPriority:NSLayoutPriorityDefaultLow forOrientation:NSLayoutConstraintOrientationHorizontal];
    [labelsStack setContentCompressionResistancePriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal];
    self.labelsStackView = labelsStack;

    NSStackView * const buttonsStack = [NSStackView stackViewWithViews:@[self.playButton, self.queueButton]];
    buttonsStack.translatesAutoresizingMaskIntoConstraints = NO;
    buttonsStack.orientation = NSUserInterfaceLayoutOrientationHorizontal;
    buttonsStack.alignment = NSLayoutAttributeCenterY;
    buttonsStack.spacing = VLCLibraryUIUnits.smallSpacing;
    [buttonsStack setContentHuggingPriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal];
    [buttonsStack setContentCompressionResistancePriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal];
    self.buttonsStackView = buttonsStack;

    [contentHostView addSubview:labelsStack];
    [contentHostView addSubview:buttonsStack];

    const CGFloat horizontalContentInset = VLCLibraryUIUnits.mediumSpacing;

    [NSLayoutConstraint activateConstraints:@[
        [labelsStack.leadingAnchor constraintEqualToAnchor:contentHostView.leadingAnchor constant:horizontalContentInset],
        [labelsStack.centerYAnchor constraintEqualToAnchor:contentHostView.centerYAnchor],
        [contentHostView.trailingAnchor constraintEqualToAnchor:buttonsStack.trailingAnchor constant:horizontalContentInset],
        [buttonsStack.centerYAnchor constraintEqualToAnchor:contentHostView.centerYAnchor],
        [buttonsStack.leadingAnchor constraintGreaterThanOrEqualToAnchor:labelsStack.trailingAnchor constant:VLCLibraryUIUnits.largeSpacing],
    ]];
    [self updateBackgroundConstraints];

    self.layer = [CALayer new];
    self.layer.backgroundColor = NSColor.clearColor.CGColor;

    if (@available(macOS 26.0, *)) {
    } else {
        self.backgroundView.layer.borderColor = NSColor.VLCSubtleBorderColor.CGColor;
        self.backgroundView.layer.borderWidth = VLCLibraryUIUnits.borderThickness;
        self.backgroundView.layer.cornerRadius = VLCLibraryUIUnits.cornerRadius;
        self.backgroundView.layer.masksToBounds = YES;

        if (@available(macOS 10.14, *)) {
            [NSApplication.sharedApplication addObserver:self
                                            forKeyPath:@"effectiveAppearance"
                                                options:NSKeyValueObservingOptionNew
                                                context:nil];
        }
    }
}

- (void)updateBackgroundConstraints
{
    if (!self.internalPaddingAddedForContentView) {
        [self.backgroundView applyConstraintsToFillSuperview];
        return;
    }
    [NSLayoutConstraint activateConstraints:@[
        [self.backgroundView.topAnchor constraintEqualToAnchor:self.topAnchor constant:self.backgroundTopInset],
        [self.backgroundView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
        [self.backgroundView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
        [self.backgroundView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-self.backgroundBottomInset],
    ]];
}

- (void)setInternalPaddingAddedForContentView:(BOOL)internalPaddingAddedForContentView
{
    if (_internalPaddingAddedForContentView == internalPaddingAddedForContentView) return;
    _internalPaddingAddedForContentView = internalPaddingAddedForContentView;
    [self updateBackgroundConstraints];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                       context:(void *)context
{
    if (@available(macOS 26.0, *)) {
        return;
    } else if ([keyPath isEqualToString:@"effectiveAppearance"]) {
        if (@available(macOS 10.14, *))  {
            NSAppearance * const appearance = change[NSKeyValueChangeNewKey];
            const BOOL isDark = [appearance.name isEqualToString:NSAppearanceNameDarkAqua] ||
                                [appearance.name isEqualToString:NSAppearanceNameVibrantDark];
            self.backgroundView.layer.borderColor = isDark ?
                NSColor.VLCDarkSubtleBorderColor.CGColor : NSColor.VLCLightSubtleBorderColor.CGColor;
        }
    }
}

- (NSTextField *)buildLabelWithFont:(NSFont *)font textColor:(NSColor *)color alignment:(NSTextAlignment)alignment
{
    NSTextField *label;
    if (@available(macOS 10.12, *)) {
        label = [NSTextField labelWithString:@""];
    } else {
        label = [[NSTextField alloc] initWithFrame:NSZeroRect];
        label.editable = NO;
        label.bezeled = NO;
        label.drawsBackground = NO;
        label.selectable = NO;
    }
    label.font = font;
    label.textColor = color;
    label.alignment = alignment;
    label.lineBreakMode = NSLineBreakByTruncatingTail;
    label.translatesAutoresizingMaskIntoConstraints = NO;
    return label;
}

- (NSButton *)buildActionButtonWithTitle:(NSString *)title action:(SEL)selector
{
    NSButton *button;
    if (@available(macOS 10.12, *)) {
        button = [NSButton buttonWithTitle:title target:self action:selector];
    } else {
        button = [[NSButton alloc] initWithFrame:NSZeroRect];
        button.title = title;
        button.target = self;
        button.action = selector;
    }
    button.bezelStyle = NSBezelStyleRounded;
    button.translatesAutoresizingMaskIntoConstraints = NO;
    if (@available(macOS 10.14, *))
        button.contentTintColor = NSColor.VLCAccentColor;
    return button;
}

- (void)setRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
{
    _representedItem = representedItem;
    [self applyRepresentedItemWithFallbackTitle:nil fallbackDetail:nil];
}

- (void)applyRepresentedItemWithFallbackTitle:(NSString *)fallbackTitle fallbackDetail:(NSString *)fallbackDetail
{
    id<VLCMediaLibraryItemProtocol> const item = self.representedItem.item;
    if (item == nil) {
        self.titleField.stringValue = fallbackTitle ?: @"";
        self.detailField.stringValue = fallbackDetail ?: @"";
        self.playButton.enabled = NO;
        self.queueButton.enabled = NO;
        return;
    }

    self.titleField.stringValue = item.displayString ?: fallbackTitle ?: @"";
    self.detailField.stringValue = item.primaryDetailString ?: fallbackDetail ?: @"";
    self.playButton.enabled = YES;
    self.queueButton.enabled = YES;
}

- (void)updateWithRepresentedItem:(VLCLibraryRepresentedItem *)representedItem
                    fallbackTitle:(NSString *)fallbackTitle
                   fallbackDetail:(NSString *)fallbackDetail
{
    self.representedItem = representedItem;
    [self applyRepresentedItemWithFallbackTitle:fallbackTitle fallbackDetail:fallbackDetail];
}

#pragma mark - Actions

- (void)play:(id)sender
{
    [self.representedItem play];
}

- (void)enqueue:(id)sender
{
    [self.representedItem queue];
}

@end
