#include "ncurses_checkbox_list.h"
#include "ncurses_checkbox.h"

namespace installer {

NcursesCheckBoxList::NcursesCheckBoxList(NCursesWindowBase* parent, int lines, int cols, int beginY, int beginX)
    :NCursesWindowBase(parent, lines, cols, beginY, beginX),
      m_singleselect(false),
      m_realselect(false),
      m_listtype(EXTRACHOICES),
      m_index(0),
      m_showindex(0),
      m_reserveX(1),
      m_heightpos(0)
{
    this->setBackground(parent->background());
    curs_set(0);
}

NcursesCheckBoxList::~NcursesCheckBoxList()
{
    clearList();
}

void NcursesCheckBoxList::setList(QVector<QPair<QString, QString>>& list, bool isusetitle, bool istitleusecheckbox)
{
    if(list.size() == 0) {
        return;
    }

    clearList();

    foreach (auto text, list) {
        NcursesCheckBox* testcheckbox = new NcursesCheckBox(this, 1, width() - 2, begy(), begx() + 2);
        testcheckbox->setIsTitleUseCheckbox(istitleusecheckbox);
        testcheckbox->setIsUseTitle(isusetitle);
        testcheckbox->setText(text.first, text.second);
        testcheckbox->setBackground(this->background());
        testcheckbox->setFocusStyle(NcursesUtil::getInstance()->list_view_item_select());
        testcheckbox->hide();

        if(m_selectitems.indexOf(text.first) != -1) {
            testcheckbox->setSelect(true);
        }
        m_ncursesCheckBoxs_vector.push_back(testcheckbox);
    }

    m_listsize = list.size();
    m_index     = 0;
    m_showindex = m_index;
    if (m_ncursesCheckBoxs_vector.size() > 0) {
        m_heightpos = m_ncursesCheckBoxs_vector.at(m_index)->getStrHeight();
    }
}

QString NcursesCheckBoxList::getCurrentTitle()
{
    if (m_ncursesCheckBoxs_vector.size() > 0) {
        return m_ncursesCheckBoxs_vector.at(m_index)->title();
    } else {
        return "";
    }
}

QString NcursesCheckBoxList::getCurrentText()
{
    if (m_ncursesCheckBoxs_vector.size() > 0) {
        return m_ncursesCheckBoxs_vector.at(m_index)->text();
    } else {
        return "";
    }
}

QString NcursesCheckBoxList::getCurrentSingleSelectTitle()
{
    if (m_singleselect) {
        for (int i = 0; i < m_ncursesCheckBoxs_vector.size(); i++) {
            if (m_ncursesCheckBoxs_vector.at(i)->isSelect()) {
                return m_ncursesCheckBoxs_vector.at(i)->title();
            }
        }
    } else {
        return "";
    }

    return {};
}

QString NcursesCheckBoxList::getCurrentSingleSelectText()
{
    if (m_singleselect) {
        for (int i = 0; i < m_ncursesCheckBoxs_vector.size(); i++) {
            if (m_ncursesCheckBoxs_vector.at(i)->isSelect()) {
                return m_ncursesCheckBoxs_vector.at(i)->text();
            }
        }
    }

    return "";
}


void NcursesCheckBoxList::clearList()
{
    foreach (NCursesWindowBase* child, m_childWindows) {
//        if (child) {
//            delete child;
//            child = nullptr;
//        }
        removeChildWindows(child);
        removeFoucsWindows(child);
    }
//    m_childWindows.clear();
//    m_foucsWindows.clear();
    m_ncursesCheckBoxs_vector.clear();
}

void NcursesCheckBoxList::onKeyPress(int keyCode)
{
    switch (keyCode) {
    case KEY_UP:
        if (m_ncursesCheckBoxs_vector.size() == 0) {
            break;
        }

        m_index--;
        if(m_index < 0){
            m_index = 0;
            m_heightpos = m_ncursesCheckBoxs_vector.at(m_index)->getStrHeight();
            break;
        } else {
            m_heightpos -= m_ncursesCheckBoxs_vector.at(m_index + 1)->getStrHeight();
            m_ncursesCheckBoxs_vector.at(m_index + 1)->setFocus(false);
        }

        if((m_heightpos == 0) && (m_index > 0)) {
            int oldheightpos = 0;
            for(int i = m_index; ; i--) {
                if((m_heightpos >= height()) || (i < 0)) {
                    oldheightpos = m_heightpos;
                    if(i < 0)
                        m_showindex = 0;
                    else
                        m_showindex = i;

                    show();
                    m_ncursesCheckBoxs_vector.at(m_index)->setFocus(false);
                    m_heightpos = oldheightpos;
                    break;
                } else {
                    m_heightpos += m_ncursesCheckBoxs_vector.at(i)->getStrHeight();
                }
            }
        }
        m_ncursesCheckBoxs_vector.at(m_index)->setFocus(true);

        if (m_listtype == OTHER) {

        } else {
            if(m_singleselect) {
                doSingleSelect();
            }
        }

        this->refresh();
        emit signal_KeyTriger(keyCode, m_listtype, m_index);
        break;

    case KEY_DOWN:
        if (m_ncursesCheckBoxs_vector.size() == 0) {
            break;
        }
        m_index++;
        if(m_index >= m_ncursesCheckBoxs_vector.size()){
            m_index = m_ncursesCheckBoxs_vector.size() - 1;
            break;
        } else {
            m_heightpos += m_ncursesCheckBoxs_vector.at(m_index)->getStrHeight();
            m_ncursesCheckBoxs_vector.at(m_index - 1)->setFocus(false);
        }

        if(m_heightpos > height()) {
            m_showindex = m_index;
            show();
            m_heightpos = m_ncursesCheckBoxs_vector.at(m_index)->getStrHeight();
        }

        m_ncursesCheckBoxs_vector.at(m_index)->setFocus(true);

        if (m_listtype == OTHER) {

        } else {
            if(m_singleselect) {
                doSingleSelect();
            }
        }

        this->refresh();
        emit signal_KeyTriger(keyCode, m_listtype, m_index);
        break;

    case 32:
        if(m_listtype == BASICENVIRONMENT) {

        } else if(m_listtype == EXTRACHOICES){
            if (m_ncursesCheckBoxs_vector.size() == 0) {
                break;
            }

             m_ncursesCheckBoxs_vector.at(m_index)->onKeyPress(keyCode);
             if(m_ncursesCheckBoxs_vector.at(m_index)->isSelect()){
                 if(m_selectitems.indexOf(m_ncursesCheckBoxs_vector.at(m_index)->title()) == -1) {
                     m_selectitems.append(m_ncursesCheckBoxs_vector.at(m_index)->title());
                 }
             } else {
                 if(m_selectitems.indexOf(m_ncursesCheckBoxs_vector.at(m_index)->title()) != -1) {
                     m_selectitems.removeOne(m_ncursesCheckBoxs_vector.at(m_index)->title());
                 }
             }
        } else if (m_listtype == OTHER) {
            if (m_ncursesCheckBoxs_vector.size() == 0) {
                break;
            }

            m_ncursesCheckBoxs_vector.at(m_index)->onKeyPress(keyCode);
            if(m_ncursesCheckBoxs_vector.at(m_index)->isSelect()){
                if(m_selectitems.indexOf(m_ncursesCheckBoxs_vector.at(m_index)->title()) == -1) {
                    m_selectitems.append(m_ncursesCheckBoxs_vector.at(m_index)->title());
                }
            } else {
                if(m_selectitems.indexOf(m_ncursesCheckBoxs_vector.at(m_index)->title()) != -1) {
                    m_selectitems.removeOne(m_ncursesCheckBoxs_vector.at(m_index)->title());
                }
            }

            if(m_singleselect) {
                for (int i = 0; i < m_ncursesCheckBoxs_vector.size(); i++) {
                    if( i != m_index)
                    {
                        m_ncursesCheckBoxs_vector.at(i)->setSelect(false);
                        m_selectitems.clear();
                    }
                }
                if(m_selectitems.indexOf(m_ncursesCheckBoxs_vector.at(m_index)->title()) == -1) {
                    m_selectitems.append(m_ncursesCheckBoxs_vector.at(m_index)->title());
                }
            }
        }
        emit signal_KeyTriger(keyCode, m_listtype, m_index);
        break;
    default:
        break;
    }

    NCursesWindowBase::onKeyPress(keyCode);
}

void NcursesCheckBoxList::show()
{
    erase();

    if((m_index >= m_ncursesCheckBoxs_vector.size()) || (m_ncursesCheckBoxs_vector.size() == 0)) {
        return;
    }

    int testheightpos = 0;
    for(int i = m_showindex; i < m_ncursesCheckBoxs_vector.size(); i++) {        
        if (i < m_showindex) {
            m_ncursesCheckBoxs_vector.at(i)->hide();
        } else {
            int testtempheightpos = testheightpos + m_ncursesCheckBoxs_vector.at(i)->getStrHeight();
            if (testtempheightpos > height()) {
                m_ncursesCheckBoxs_vector.at(i)->hide();
                continue;
            } else {
                m_ncursesCheckBoxs_vector.at(i)->moveWindowTo(begy() + testheightpos, begx() + 1);
                m_ncursesCheckBoxs_vector.at(i)->show();
                m_ncursesCheckBoxs_vector.at(i)->refresh();

                testheightpos += m_ncursesCheckBoxs_vector.at(i)->getStrHeight();
            }
        }
    }

    if (isOnFoucs()) {
        m_ncursesCheckBoxs_vector.at(m_index)->setFocus(true);
    } else {
        chtype testchtype = m_ncursesCheckBoxs_vector.at(m_index)->getFocusStyle();
        m_ncursesCheckBoxs_vector.at(m_index)->setbkgd(testchtype);
    }

    if(m_listtype == BASICENVIRONMENT) {
        doSingleSelect();
    }

    m_ncursesCheckBoxs_vector.at(m_index)->setSelect(m_ncursesCheckBoxs_vector.at(m_index)->isSelect());

}

void NcursesCheckBoxList::drawFoucs()
{
    //m_foucs ? attron(A_REVERSE) : attroff(A_REVERSE);
}

void NcursesCheckBoxList::selectAll(bool selectall)
{
    if (selectall) {
        for(int i = 0; i < m_ncursesCheckBoxs_vector.size(); i++) {
            m_ncursesCheckBoxs_vector.at(i)->setSelect(true);
            if(m_selectitems.indexOf(m_ncursesCheckBoxs_vector.at(i)->title()) == -1) {
                m_selectitems.append(m_ncursesCheckBoxs_vector.at(i)->title());
            }
        }
    } else {
        for(int i = 0; i < m_ncursesCheckBoxs_vector.size(); i++) {
            m_ncursesCheckBoxs_vector.at(i)->setSelect(false);
            if(m_selectitems.indexOf(m_ncursesCheckBoxs_vector.at(i)->title()) != -1) {
                m_selectitems.removeOne(m_ncursesCheckBoxs_vector.at(i)->title());
            }
        }
    }
}

void NcursesCheckBoxList::setFocus(bool foucs)
{
    m_foucs = foucs;
    show();
    if (m_ncursesCheckBoxs_vector.size() > 0) {
        if (foucs) {
            m_ncursesCheckBoxs_vector.at(m_index)->setFocus(true);
        } else {
            chtype testchtype = m_ncursesCheckBoxs_vector.at(m_index)->getFocusStyle();
            m_ncursesCheckBoxs_vector.at(m_index)->setbkgd(testchtype);
        }
    }
}

void NcursesCheckBoxList::doSingleSelect()
{
    foreach(NcursesCheckBox* testitem, m_ncursesCheckBoxs_vector) {
        testitem->setSelect(false);
        m_selectitems.clear();
    }

    if (m_ncursesCheckBoxs_vector.size() > 0) {
        m_ncursesCheckBoxs_vector.at(m_index)->setSelect(true);
        if(m_selectitems.indexOf(m_ncursesCheckBoxs_vector.at(m_index)->title()) == -1) {
            m_selectitems.append(m_ncursesCheckBoxs_vector.at(m_index)->title());
        }
    }

    this->refresh();
}

}
