/*
 * File Name: text_tasks.cpp
 */

/*
 * This file is part of uds-plugin-plaintext.
 *
 * uds-plugin-plaintext 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.
 *
 * uds-plugin-plaintext 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/>.
 */

/**
 * Copyright (C) 2008 iRex Technologies B.V.
 * All rights reserved.
 */

#include "plugin_render_result.h"

#include "log.h"
#include "text_tasks.h"
#include "text_view.h"

namespace text
{

InitializationTask::InitializationTask(TextView *view)
: text_view(view)
{
}

InitializationTask::~InitializationTask()
{
}

void InitializationTask::execute()
{
    text_view->initialize();
}

DeinitializationTask::DeinitializationTask(TextView *view)
: text_view(view)
{
}

DeinitializationTask::~DeinitializationTask()
{
}

void DeinitializationTask::execute()
{
    text_view->deinitialize();
}

PaginationTask::PaginationTask(TextView *view, const Position& _start, bool _is_child)
: text_view(view), start_pos(_start), is_child(_is_child)
{
}

PaginationTask::~PaginationTask()
{
}

void PaginationTask::execute()
{
    if (!is_child)
    {
        // Tell listener that pagination starts.
        LOGPRINTF("About to send pagination start signal.");
        text_view->pagination_start_signal.broadcast(1);
    }

    bool pagination_done = false;
    while (!is_aborted())
    {
        if (text_view->paginate(start_pos))
        {
            // Pagination is complete.
            pagination_done = true;
            break;
        }
    }

    if (pagination_done)
    {
        // Tell listener that pagination is done.
        unsigned int total_pages = text_view->get_page_count();
        unsigned int current_page = text_view->get_current_page_index();
        LOGPRINTF("About to send pagination done signal.");
        text_view->pagination_end_signal.broadcast(current_page, total_pages);
    }
    else
    {
        // We are aborted.
        LOGPRINTF("Pagination aborted...");
        abort_signal.broadcast(start_pos);
    }
}


PaginationAbortTask::PaginationAbortTask(TextView *view)
: text_view(view)
{
    TRACEFUNCTION();
}

PaginationAbortTask::~PaginationAbortTask()
{
    TRACEFUNCTION();
}

void PaginationAbortTask::execute()
{
    TRACEFUNCTION();

    //
    // Dummy task to abort pagination
    //
    
    // Example usage:
    //   PaginationAbortTask *task = new PaginationAbortTask();
    //   thread.prepend_task(task, true /* Cancel running task */);
}

RenderTask::RenderTask(unsigned int     _id,
                       TextView        *_view,
                       const Position&  _pos,
                       void            *_user_data,
                       unsigned char   *_bmp)
: id(_id)
, text_view(_view)
, start_pos(_pos)
, user_data(_user_data)
, bmp(_bmp)
{
}

RenderTask::~RenderTask()
{
}

void RenderTask::execute()
{
    Position end_pos = text_view->render(bmp, start_pos);

    // Tell listener that render done.
    text_view->render_done_signal.broadcast(id, start_pos, end_pos, user_data);
}

SearchTask::SearchTask(TextModel *_model, SearchContext* _sc)
: text_model(_model), sc(_sc)
{
}

SearchTask::~SearchTask()
{
}

void SearchTask::execute()
{
    std::vector<Range> result_ranges;
    bool search_done = false;
    while (!is_aborted() &&
           text_model->get_aborting_search_task_id() != sc->search_id)
    {
        if (text_model->search(result_ranges, sc))
        {
            // We reached the start/end of the document, 
            // or we find an occurrence if the SearchType is SEARCH_NEXT.
            search_done = true;
            break;
        }
    }

    if (is_aborted())
    {
        LOGPRINTF("Search task is aborted by another task...");
        abort_signal.broadcast(sc);
    }

    if (search_done)
    {
        // Tell listeners search task is done.
        text_model->search_done_signal.broadcast(result_ranges, sc);
    }
    else
    {
        // We are aborted, do nothing.
        LOGPRINTF("Search task is aborted by user...");
    }
}

}

