#include "yacreader_macosx_toolbar.h"
#include "QtWidgets/qmainwindow.h"

#include <QtGlobal>
#include <QtWidgets>

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <QWidget>
#include <QMacNativeWidget>
#include <qmacfunctions.h>
#include <qpa/qplatformnativeinterface.h>
#include <QsLog.h>

#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>

#import "shortcuts_manager.h"

//----------------------------
// A custom items separator for NSToolbar
@interface CustomSeparator : NSView

@end

@implementation CustomSeparator

- (void)drawRect:(NSRect)rect
{
    [[NSColor colorWithDeviceRed:0.5 green:0.5 blue:0.5 alpha:1] setFill];
    NSRectFill(rect);
    [super drawRect:rect];
}

@end

//----------------------------
// Toolbar delegate, needed for allow disabled/enabled items
@interface MyToolbarDelegate : NSObject <NSToolbarDelegate> {
@public
    YACReaderMacOSXToolbar *mytoolbar;
}

- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdent willBeInsertedIntoToolbar:(BOOL)willBeInserted;
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar;
- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar;
//- (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar;
- (IBAction)itemClicked:(id)sender;
- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem;
@end

@implementation MyToolbarDelegate

- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar
{
    Q_UNUSED(toolbar);

    NSMutableArray *array = [[NSMutableArray alloc] init];

    QList<QMacToolBarItem *> items = mytoolbar->items();
    foreach (const QMacToolBarItem *item, items) {
        [array addObject:item->nativeToolBarItem().itemIdentifier];
    }
    return array;
}

- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
{
    Q_UNUSED(toolbar);

    NSMutableArray *array = [[NSMutableArray alloc] init];

    QList<QMacToolBarItem *> items = mytoolbar->items();
    foreach (const QMacToolBarItem *item, items) {
        [array addObject:item->nativeToolBarItem().itemIdentifier];
    }
    return array;
}

/*
- (NSArray *)toolbarSelectableItemIdentifiers: (NSToolbar *)toolbar
{
    Q_UNUSED(toolbar);

    NSMutableArray *array = [[NSMutableArray alloc] init];

    QList<QMacToolBarItem *> items = mytoolbar->items();
    foreach (const QMacToolBarItem * item, items) {
        [array addObject : item->nativeToolBarItem().itemIdentifier];
    }
    return array;
    //NSMutableArray *array = toolbarPrivate->getItemIdentifiers(toolbarPrivate->items, true);
    //[array addObjectsFromArray:toolbarPrivate->getItemIdentifiers(toolbarPrivate->allowedItems, true)];
    //return array;
}*/

- (IBAction)itemClicked:(id)sender
{
    if ([sender respondsToSelector:@selector(itemIdentifier)]) {
        NSToolbarItem *item = reinterpret_cast<NSToolbarItem *>(sender);

        QString identifier = QString::fromNSString([item itemIdentifier]);
        QMacToolBarItem *toolButton = reinterpret_cast<QMacToolBarItem *>(identifier.toULongLong());
        Q_EMIT toolButton->activated();
    }
}

- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)willBeInserted
{
    Q_UNUSED(toolbar);
    Q_UNUSED(willBeInserted);
    QList<QMacToolBarItem *> items = mytoolbar->items();

    foreach (const QMacToolBarItem *item, items) {
        NSToolbarItem *toolbarItem = item->nativeToolBarItem();
        if ([toolbarItem.itemIdentifier isEqual:itemIdentifier]) {

            [toolbarItem setTarget:self];
            [toolbarItem setAction:@selector(itemClicked:)];

            return toolbarItem;
        }
    }
    return nil;
}

- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem
{
    QString identifier = QString::fromNSString(theItem.itemIdentifier);

    if (mytoolbar->actions.contains(identifier)) {
        return mytoolbar->actions.value(identifier)->isEnabled();
    } else
        return NO;
}
@end

//----------------------------
// detect changes in native text field
// TODO implement validation and auto completion
@interface MyTextFieldDelegate : NSObject <NSTextFieldDelegate> {
@public
    YACReaderMacOSXSearchLineEdit *mylineedit;
}
@end

@implementation MyTextFieldDelegate

- (void)controlTextDidChange:(NSNotification *)notification
{
    NSTextField *textField = [notification object];
    NSLog(@"%@", [textField stringValue]);
    Q_EMIT mylineedit->filterChanged(QString::fromNSString([textField stringValue]));
}

@end
//----------------------------

YACReaderMacOSXToolbar::YACReaderMacOSXToolbar(QObject *parent)
    : viewSelector(0)
{
    // setup native toolbar
    nativeToolBar = nativeToolbar();
    [nativeToolBar setDisplayMode:NSToolbarDisplayModeIconOnly];
    [nativeToolBar setAllowsUserCustomization:NO];

    delegate = [[MyToolbarDelegate alloc] init];
    ((MyToolbarDelegate *)delegate)->mytoolbar = this;
    [nativeToolBar setDelegate:(MyToolbarDelegate *)delegate];

#ifdef YACREADER_LIBRARY
    NSWindow *nswindow = (NSWindow *)qApp->platformNativeInterface()->nativeResourceForWindow("nswindow", ((QMainWindow *)parent)->windowHandle());
    if ([nswindow respondsToSelector:@selector(setTitleVisibility:)]) {
        yosemite = true;
        // TODO yosemite new constants are not found in compilation time
        [nswindow setTitleVisibility:NSWindowTitleHidden];
        // TODO NSFullSizeContentViewWindowMask produces an offset in the windows' content
        // nswindow.styleMask |= 1 << 15; // NSFullSizeContentViewWindowMask;
        [nativeToolBar setSizeMode:NSToolbarSizeModeSmall]; // TODO figure out how to load specific images in Yosemite
    } else {
        [nativeToolBar setSizeMode:NSToolbarSizeModeSmall];
        yosemite = false;
    }
#else
    yosemite = false;
    [nativeToolBar setAutosavesConfiguration:YES]; // TODO this doesn't work
    [nativeToolBar setSizeMode:NSToolbarSizeModeSmall];
#endif
}

void YACReaderMacOSXToolbar::addAction(QAction *action)
{
    QMacToolBarItem *toolBarItem = addItem(action->icon(), action->text());
    if (action->data().toString() == TOGGLE_COMICS_VIEW_ACTION_YL)
        viewSelector = toolBarItem;
    connect(toolBarItem, &QMacToolBarItem::activated, action, [=] { emit action->triggered(); });

    NSToolbarItem *nativeItem = toolBarItem->nativeToolBarItem();
    actions.insert(QString::fromNSString(nativeItem.itemIdentifier), action);

    MacToolBarItemWrapper *wrapper = new MacToolBarItemWrapper(action, toolBarItem);
    // wrapper->actionToogled(true);
}

void YACReaderMacOSXToolbar::addDropDownItem(const QList<QAction *> &actions, const QAction *defaultAction)
{
    // TODO
}

void YACReaderMacOSXToolbar::addSpace(int size)
{
    QMacToolBarItem *toolBarItem = addItem(QIcon(), "");
    NSToolbarItem *nativeItem = toolBarItem->nativeToolBarItem();

    static const NSRect frameRect = { { 0.0, 0.0 }, { CGFloat(size), 16.0 } };
    NSView *view = [[NSView alloc] initWithFrame:frameRect];

    [nativeItem setView:view];
}

// reimplemented for convenience
void YACReaderMacOSXToolbar::addSeparator()
{
    // QMacToolBar::addSeparator();

    QMacToolBarItem *toolBarItem = addItem(QIcon(), "");
    NSToolbarItem *nativeItem = toolBarItem->nativeToolBarItem();

    static const NSRect frameRect = { { 0.0, 0.0 }, { 1, 16.0 } };
    CustomSeparator *view = [[CustomSeparator alloc] initWithFrame:frameRect];

    [nativeItem setView:view];
}

void YACReaderMacOSXToolbar::addStretch()
{
    QMacToolBarItem *toolBarItem = addItem(QIcon(), "");
    toolBarItem->setStandardItem(QMacToolBarItem::FlexibleSpace);
}

void YACReaderMacOSXToolbar::addWidget(QWidget *widget)
{
    // TODO fix it
    /* QMacNativeWidget *nativeWidget = new QMacNativeWidget();
    QVBoxLayout *layout = new QVBoxLayout();
    layout->addWidget(widget);
    nativeWidget->setLayout(layout);


    NSView *nativeWidgetView = reinterpret_cast<NSView *>(nativeWidget->winId());
    QMacToolBarItem *toolBarItem = addItem(QIcon(),"");
    NSToolbarItem * nativeItem = toolBarItem->nativeToolBarItem();
    [nativeItem setView:nativeWidgetView];*/
}

void YACReaderMacOSXToolbar::show()
{
    [nativeToolBar setVisible:YES];
}

void YACReaderMacOSXToolbar::hide()
{
    [nativeToolBar setVisible:NO];
}

YACReaderMacOSXSearchLineEdit *YACReaderMacOSXToolbar::addSearchEdit()
{
    QMacToolBarItem *toolBarItem = addItem(QIcon(), "");
    NSToolbarItem *nativeItem = toolBarItem->nativeToolBarItem();

    YACReaderMacOSXSearchLineEdit *searchEdit = new YACReaderMacOSXSearchLineEdit();

    if (yosemite)
        [nativeItem setView:(NSTextField *)searchEdit->getNSTextField()];
    else {
        static const NSRect searchEditFrameRect = { { 0.0, 0.0 }, { 165, 26.0 } };
        NSView *view = [[NSView alloc] initWithFrame:searchEditFrameRect];
        [view addSubview:((NSTextField *)searchEdit->getNSTextField())];
        [nativeItem setView:view];
    }

    return searchEdit;
}

// deprecated
QAction *YACReaderMacOSXToolbar::addFitToWidthSlider(QAction *attachToAction)
{
    QMacToolBarItem *toolBarItem = addItem(QIcon(":/images/viewer_toolbar/toWidthSlider.png"), "fit to width slider");

    NSToolbarItem *nativeItem = toolBarItem->nativeToolBarItem();
    actions.insert(QString::fromNSString(nativeItem.itemIdentifier), attachToAction);

    QAction *action = new QAction("", attachToAction->parent());

    connect(toolBarItem, &QMacToolBarItem::activated, action, [=] { emit action->triggered(); });

    return action;
}

void YACReaderMacOSXToolbar::updateViewSelectorIcon(const QIcon &icon)
{
    if (viewSelector)
        viewSelector->setIcon(icon);
}

void YACReaderMacOSXToolbar::attachToWindow(QMainWindow *window)
{
    QMacToolBar::attachToWindow(window->windowHandle());
}

YACReaderMacOSXSearchLineEdit::YACReaderMacOSXSearchLineEdit()
    : QObject()
{
    NSRect searchEditFrameRect = { { 0.0, -3.0 }, { 165, 32.0 } };
    // NSTextField * searchEdit = [[NSTextField alloc] initWithFrame:searchEditFrameRect];

    NSTextField *searchEdit = [[NSSearchField alloc] initWithFrame:searchEditFrameRect];
    //[searchEdit setBezelStyle:NSTextFieldRoundedBezel];

    [[searchEdit cell] setPlaceholderString:@"type to search"];

    MyTextFieldDelegate *delegate = [[MyTextFieldDelegate alloc] init];
    delegate->mylineedit = this;
    [searchEdit setDelegate:delegate];

    nstextfield = searchEdit;
}

void YACReaderMacOSXSearchLineEdit::setFocus(Qt::FocusReason reason)
{
    Q_UNUSED(reason)

    [((NSTextField *)nstextfield) becomeFirstResponder];
}

void *YACReaderMacOSXSearchLineEdit::getNSTextField()
{
    return nstextfield;
}

QString YACReaderMacOSXSearchLineEdit::text()
{
    return QString::fromNSString([((NSTextField *)nstextfield) stringValue]);
}

void YACReaderMacOSXSearchLineEdit::clear()
{
    [((NSTextField *)nstextfield) setStringValue:@""];
    emit filterChanged("");
}

void YACReaderMacOSXSearchLineEdit::clearText()
{
    // TODO be sure that this will not generate any event....
    [((NSTextField *)nstextfield) setStringValue:@""];
}

void YACReaderMacOSXSearchLineEdit::setDisabled(bool disabled)
{
    [((NSTextField *)nstextfield) setEnabled:!disabled];
}

void YACReaderMacOSXSearchLineEdit::setEnabled(bool enabled)
{
    [((NSTextField *)nstextfield) setEnabled:enabled];
}

MacToolBarItemWrapper::MacToolBarItemWrapper(QAction *action, QMacToolBarItem *toolbaritem)
    : action(action), toolbaritem(toolbaritem)
{
    if (action->isCheckable()) {
        connect(action, &QAction::toggled, this, &MacToolBarItemWrapper::actionToggled);
        connect(toolbaritem, &QMacToolBarItem::activated, action, &QAction::toggle);
        updateIcon(action->isChecked());
    }
}

void MacToolBarItemWrapper::actionToggled(bool toogled)
{
    updateIcon(toogled);
}

void MacToolBarItemWrapper::updateIcon(bool enabled)
{
    if (enabled) {
        QIcon icon = action->icon();
        QPixmap tempPixmap = icon.pixmap(QSize(24, 24));
        QPainter painter;
        painter.begin(&tempPixmap);
        painter.fillRect(QRect(3, 21, 18, 1), QColor("#3F3F3F"));
        painter.fillRect(QRect(3, 22, 18, 1), QColor("#6E6E6E"));
        painter.fillRect(QRect(3, 23, 18, 1), QColor("#EEEEEE"));
        painter.end();

        toolbaritem->setIcon(QIcon(tempPixmap));
    } else
        toolbaritem->setIcon(action->icon());
}
#else

#ifdef YACREADER_LIBRARY

YACReaderMacOSXToolbar::YACReaderMacOSXToolbar(QWidget *parent)
    : YACReaderMainToolBar(parent)
{
    backButton->setIconSize(QSize(24, 24));
    forwardButton->setIconSize(QSize(24, 24));
    settingsButton->setIconSize(QSize(24, 24));
    serverButton->setIconSize(QSize(24, 24));
    helpButton->setIconSize(QSize(24, 24));
    toggleComicsViewButton->setIconSize(QSize(24, 24));
}

QSize YACReaderMacOSXToolbar::sizeHint() const
{
    return QSize(400, 36);
}

void YACReaderMacOSXToolbar::addAction(QAction *action)
{
    if (backButton->defaultAction() == nullptr) {
        backButton->setDefaultAction(action);
        return;
    }
    if (forwardButton->defaultAction() == nullptr) {
        forwardButton->setDefaultAction(action);
        return;
    }
    if (settingsButton->defaultAction() == nullptr) {
        settingsButton->setDefaultAction(action);
        return;
    }
    if (serverButton->defaultAction() == nullptr) {
        serverButton->setDefaultAction(action);
        return;
    }
    if (helpButton->defaultAction() == nullptr) {
        helpButton->setDefaultAction(action);
        return;
    }
    if (toggleComicsViewButton->defaultAction() == nullptr) {
        toggleComicsViewButton->setDefaultAction(action);
        return;
    }
}

void YACReaderMacOSXToolbar::addSpace(int size)
{
}

void YACReaderMacOSXToolbar::addStretch()
{
}

YACReaderMacOSXSearchLineEdit *YACReaderMacOSXToolbar::addSearchEdit()
{
    auto search = new YACReaderMacOSXSearchLineEdit();

    setSearchWidget(search);

    return search;
}

void YACReaderMacOSXToolbar::updateViewSelectorIcon(const QIcon &icon)
{
}

void YACReaderMacOSXToolbar::attachToWindow(QMainWindow *window)
{
    auto toolbar = new QToolBar();

    toolbar->addWidget(this);
    toolbar->setMovable(false);

    window->addToolBar(toolbar);
}

void YACReaderMacOSXToolbar::paintEvent(QPaintEvent *)
{
}

#else

YACReaderMacOSXToolbar::YACReaderMacOSXToolbar(QWidget *parent)
    : QToolBar(parent)
{
    setMovable(false);
    setIconSize(QSize(24, 24));
}

void YACReaderMacOSXToolbar::attachToWindow(QMainWindow *window)
{
    window->setUnifiedTitleAndToolBarOnMac(true);
    window->addToolBar(this);
}

void YACReaderMacOSXToolbar::addStretch()
{
}

#endif

#endif