/*
 * QT Client for X2GoKDrive
 * Copyright (C) 2018-2023 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de>
 * Copyright (C) 2018-2023 phoca-GmbH
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 *
 */

#include <menuframe.h>
#include <QMouseEvent>
#include <QCursor>
#include <QToolButton>
#include <QLabel>
#include <QMenu>
#include <QHBoxLayout>
#include <QSettings>
#include <QTimer>

#include "client.h"





#include <QPainter>

RotatedLabel::RotatedLabel(QWidget *parent): QLabel(parent)
{
}

RotatedLabel::RotatedLabel(const QString &text, QWidget *parent): QLabel(text, parent)
{
}

void RotatedLabel::setOrientation(RotatedLabel::orient ort)
{
    orientation=ort;
}

void RotatedLabel::mouseDoubleClickEvent(QMouseEvent*)
{
    emit doubleClick();
}


void RotatedLabel::paintEvent(QPaintEvent* ev)
{
    switch (orientation)
    {
        case NORMAL:
            QLabel::paintEvent(ev);
            return;
        case LEFT:
        {
            QPainter painter(this);
            painter.translate(8,2);
            painter.rotate(90);
            painter.drawText(0,0,text());
            break;
        }
        case RIGHT:
        {
            QPainter painter(this);
            painter.translate( sizeHint().height()-4,sizeHint().width()+1);
            painter.rotate(270);
            painter.drawText(0,0,text());
            break;
        }
    }
}

MenuFrame::MenuFrame(QWidget* parent, QMenu* menu):QFrame(parent)
{
     setMouseTracking(true);
     setObjectName("FSMenuBar");

     bPin=new QToolButton(this);
     bPin->setIcon(QIcon(":/img/pin.svg"));
     bPin->setCheckable(true);
     bPin->setToolTip(tr("Pin menu bar"));


     connect(bPin, SIGNAL(toggled(bool)), this, SLOT(setPinned(bool)));


     QHBoxLayout* ml=new QHBoxLayout(this);

     hLayout=new QHBoxLayout();
     vLayout=new QVBoxLayout();

     ml->addLayout(hLayout);
     ml->addLayout(vLayout);

     defaultMargin=ml->margin();
     defaultSpacing=ml->spacing();

     ml->setSpacing(0);
     ml->setMargin(0);


     viewMenu=new QToolButton(this);

     viewMenu->setMenu(menu);
     viewMenu->setPopupMode(QToolButton::InstantPopup);
     viewMenu->setToolTip(tr("View"));
     viewMenu->setIcon(QIcon(":/img/svg/view.svg"));

     capt=new RotatedLabel("", this);
     capt->setToolTip(tr("Double click to change window title\nDrag to change position"));

     connect(capt, SIGNAL(doubleClick()), this,SIGNAL(editCaption()));

     bDisc=new QToolButton(this);
     bDisc->setToolTip(tr("Disconnect"));
     bDisc->setIcon(QIcon(":/img/svg/network-disconnect.svg"));
     Client* client=(Client*)parent;
     connect(bDisc, SIGNAL(clicked(bool)),client, SLOT(slotDisconnect()));


     bMin=new QToolButton(this);
     bMin->setToolTip(tr("Minimize"));
     bMin->setIcon(QIcon(":/img/svg/minimize.svg"));
     connect(bMin, SIGNAL(clicked(bool)),client, SLOT(showMinimized()));

     QSettings s( "Obviously Nice","x2gokdriveclient");
     isPinned=s.value("pinned",false).toBool();

     position=s.value("position",0.5).toDouble();

     QString orstr=s.value("orientation", "top").toString();

     if(orstr=="bottom")
         orientation=BOTTOM;
     if(orstr=="left")
         orientation=LEFT;
     if(orstr=="right")
         orientation=RIGHT;


     setFocusPolicy(Qt::NoFocus);
     bPin->setFocusPolicy(Qt::NoFocus);
     bMin->setFocusPolicy(Qt::NoFocus);
     bDisc->setFocusPolicy(Qt::NoFocus);
     viewMenu->setFocusPolicy(Qt::NoFocus);
     capt->setFocusPolicy(Qt::NoFocus);


     setupFrame();
     adjustPosition();
     bPin->setChecked(isPinned);
     hovered=true;
     setHasPointer(false);
     applyStyle();

}

void MenuFrame::setupFrame()
{
    if(hLayout->count())
    {
        hLayout->removeWidget(bPin);
        hLayout->removeWidget(viewMenu);
        hLayout->removeWidget(capt);
        hLayout->removeWidget(bMin);
        hLayout->removeWidget(bDisc);
    }
    if(vLayout->count())
    {
        vLayout->removeWidget(bPin);
        vLayout->removeWidget(viewMenu);
        vLayout->removeWidget(capt);
        vLayout->removeWidget(bMin);
        vLayout->removeWidget(bDisc);
    }

    switch(orientation)
    {
        case TOP:
        case BOTTOM:
            vLayout->setSpacing(0);
            vLayout->setMargin(0);
            hLayout->setSpacing(defaultSpacing);
            hLayout->setMargin(defaultMargin);
            hLayout->addWidget(bPin);
            hLayout->addWidget(viewMenu);
            hLayout->addWidget(capt);
            hLayout->addWidget(bMin);
            hLayout->addWidget(bDisc);
            capt->setOrientation(RotatedLabel::NORMAL);
            setMinimumHeight(bDisc->sizeHint().height()+defaultMargin*2);
            setMaximumHeight(bDisc->sizeHint().height()+defaultMargin*2);
            setMinimumWidth(defaultSpacing*4+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4);
            setMaximumWidth(defaultSpacing*4+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4);
            break;
        case LEFT:
            capt->setOrientation(RotatedLabel::LEFT);
            // fall through
        case RIGHT:
            if(orientation!=LEFT)
                capt->setOrientation(RotatedLabel::RIGHT);
            hLayout->setSpacing(0);
            hLayout->setMargin(0);
            vLayout->setSpacing(defaultSpacing);
            vLayout->setMargin(defaultMargin);
            vLayout->addWidget(bPin);
            vLayout->addWidget(viewMenu);
            vLayout->addWidget(capt);
            vLayout->addWidget(bMin);
            vLayout->addWidget(bDisc);
            setMinimumWidth(bDisc->sizeHint().height()+defaultMargin*2);
            setMaximumWidth(bDisc->sizeHint().height()+defaultMargin*2);
            setMinimumHeight(defaultSpacing*5+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4);
            setMaximumHeight(defaultSpacing*5+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4);
            break;
    }

}


void MenuFrame::adjustPosition()
{
    int y=0;
    int x=0;

//     Client::KDRStdErr()<<"Widget width"<<width();
    switch(orientation)
    {
        case BOTTOM:
            y=parentWidget()->height()-height();
            // fall through
        case TOP:
        {
            if(position==0)
            {
                x=0;
            }
            else if(position==1)
            {
                x=parentWidget()->width()-width()-1;
            }
            else
            {
                x=parentWidget()->width()*position-width()/2;
                if(x<11)
                {
                    x=11;
                }
                if(x+11>parentWidget()->width()-width())
                {
                    x=parentWidget()->width()-width()-11;
                }
            }
            break;
        }
        case RIGHT:
            x=parentWidget()->width()-width();
            // fall through
        case LEFT:
        {
            if(position==0)
            {
                y=0;
            }
            else if(position==1)
            {
                y=parentWidget()->height()-height()-1;
            }
            else
            {
                y=parentWidget()->height()*position-height()/2;
                if(y<11)
                {
                    y=11;
                }
                if(y+11>parentWidget()->height()-height())
                {
                    y=parentWidget()->height()-height()-11;
                }
            }
            break;
        }
    }
    move(x,y);

    hovered=true;
    setHasPointer(false);
}


void MenuFrame::setCaption(const QString& text)
{
    capt->setText(text);
    switch(orientation)
    {
        case TOP:
        case BOTTOM:
            setMinimumWidth(defaultSpacing*4+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4+4);
            setMaximumWidth(defaultSpacing*4+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4+4);
            break;
        case LEFT:
        case RIGHT:
            setMinimumHeight(defaultSpacing*5+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4+4);
            setMaximumHeight(defaultSpacing*5+defaultMargin*2+capt->sizeHint().width()+bPin->sizeHint().width()*4+4);
            break;
    }

    QTimer::singleShot(20,this, SLOT(adjustPosition()));
}

void MenuFrame::applyStyle()
{
    QPalette pal=bPin->palette();
    QString bgCol;
    QColor col=pal.color(QPalette::Window);

    bgCol.sprintf("rgba(%d,%d,%d,%d)",col.red(), col.green(), col.blue() ,col.alpha()) ;

    switch(orientation)
    {
        case TOP:
            setStyleSheet("QFrame#FSMenuBar{background-color:"+bgCol+";border-bottom-right-radius:5px;border-bottom-left-radius:5px;border-left-style:solid;border-right-style:solid;border-bottom-style:solid;border-width:1px;border-color:grey;}");
            break;
        case BOTTOM:
            setStyleSheet("QFrame#FSMenuBar{background-color:"+bgCol+";border-top-right-radius:5px;border-top-left-radius:5px;border-left-style:solid;border-right-style:solid;border-top-style:solid;border-width:1px;border-color:grey;}");
            break;
        case LEFT:
            setStyleSheet("QFrame#FSMenuBar{background-color:"+bgCol+";border-top-right-radius:5px;border-bottom-right-radius:5px;border-right-style:solid;border-bottom-style:solid;border-top-style:solid;border-width:1px;border-color:grey;}");
            break;
        case RIGHT:
            setStyleSheet("QFrame#FSMenuBar{background-color:"+bgCol+";border-top-left-radius:5px;border-bottom-left-radius:5px;border-left-style:solid;border-bottom-style:solid;border-top-style:solid;border-width:1px;border-color:grey;}");
            break;
    }
}


void MenuFrame::mouseMoveEvent(QMouseEvent* event)
{
    setHasPointer(true);
    if(!drag)
        return;
    int deltaX=event->screenPos().x()-startPosX;
    startPosX=event->screenPos().x();

    int deltaY=event->screenPos().y()-startPosY;
    startPosY=event->screenPos().y();


    int localY=event->screenPos().y() - parentWidget()->geometry().y();
    int localX=event->screenPos().x() - parentWidget()->geometry().x();

    int rDist=parentWidget()->width()-localX;
    int bDist=parentWidget()->height()-localY;

    if(rDist<localX && rDist<localY && rDist<bDist)
    {
        if(orientation!=RIGHT)
        {
            orientation=RIGHT;
            applyStyle();
            setupFrame();
        }
    }else if(localY<rDist && localY<localX && localY<bDist)
    {
        if(orientation!=TOP)
        {
            orientation=TOP;
            applyStyle();
            setupFrame();
        }
    }
    else if(bDist<localY && bDist<localX && bDist<rDist)
    {
        if(orientation!=BOTTOM)
        {
            orientation=BOTTOM;
            applyStyle();
            setupFrame();
        }
    }
    else
    {
        if(orientation!=LEFT)
        {
            orientation=LEFT;
            applyStyle();
            setupFrame();
        }
    }

    int newX=0;
    int newY=0;

    switch(orientation)
    {
        case BOTTOM:
            newY=parentWidget()->height()-height();
            // fall through
        case TOP:
        {
            newX=x()+deltaX;
            if(newX<0)
                newX=0;
            if(newX+width() > parentWidget()->width())
                newX=parentWidget()->width() - width();

            move(newX,newY);
            position=(newX+width()/2.)/parentWidget()->width();
            if(newX<=10)
                position=0;
            if(newX+width()>=parentWidget()->width()-10)
                position=1;
        }
        break;
        case RIGHT:
            newX=parentWidget()->width()-width();
            // fall through
        case LEFT:
        {
            newY=y()+deltaY;
            if(newY<0)
                newY=0;
            if(newY+height() > parentWidget()->height())
                newY=parentWidget()->height()-height();
            move(newX, newY);
            position=(newY+height()/2.)/parentWidget()->height();
            if(newY<=10)
                position=0;
            if(newY+height()>=parentWidget()->height()-10)
                position=1;
        }
        break;
    }

    QSettings s( "Obviously Nice","x2gokdriveclient");
    s.setValue("position",position);
    switch(orientation)
    {
        case TOP:
            s.setValue("orientation","top");
            break;
        case BOTTOM:
            s.setValue("orientation","bottom");
            break;
        case LEFT:
            s.setValue("orientation","left");
            break;
        case RIGHT:
            s.setValue("orientation","right");
            break;

    }

}


void MenuFrame::setHasPointer(bool hasPointer)
{
    if(hasPointer==hovered)
        return;
    hovered=hasPointer;
//     Client::KDRStdErr()<<"hovered:"<<hovered;
    int newY=y();
    int newX=x();

    if(hovered || isPinned)
    {
        switch(orientation)
        {
            case TOP: newY=0; break;
            case BOTTOM: newY=parentWidget()->height()-height(); break;
            case LEFT: newX=0;break;
            case RIGHT:newX=parentWidget()->width()-width();break;
        }
    }
    else
    {
        switch(orientation)
        {
            case TOP: newY=0-height()+5; break;
            case BOTTOM: newY=parentWidget()->height()-5; break;
            case LEFT: newX=0-width()+5;break;
            case RIGHT: newX=parentWidget()->width()-5; break;
        }
    }
    move(newX, newY);
}


void MenuFrame::mousePressEvent(QMouseEvent* event)
{
    drag=true;
    startPosX=event->screenPos().x();
    startPosY=event->screenPos().y();
    setCursor(Qt::SizeAllCursor);
}

void MenuFrame::mouseReleaseEvent(QMouseEvent* )
{
    drag=false;
    setCursor(Qt::ArrowCursor);
}

void MenuFrame::setPinned(bool toggled)
{
    Client::KDRStdErr()<<"pinned: "<<toggled;
    isPinned=toggled;
    QSettings s( "Obviously Nice","x2gokdriveclient");
    s.setValue("pinned",isPinned);
}

void MenuFrame::enableViewMenu(bool enabled)
{
    viewMenu->setEnabled(enabled);
}
