require( "scripts/game/deftasks.lua" );
require( "scripts/game/deftime.lua" );
require( "scripts/game/defpersonage.lua" );
-- персонаж "brother"
GameObject = {
-- main parameters
    Params = {
        ID="brother";       --   не изменять(парамер, определяющий анимационый конфиг, соответствующий персонажу)
        width=1;           --  ширина обьекта(при прохождении самого обьекта не учитывается )
        height=1;          --  высота  обьекта(при прохождении самого обьекта не учитывается )
        speed=800;         -- скорость перемещения обьект
        speed_aaa = 400;   -- скорость пугания
        speed_normal = 800; --обычная скорость
        LemonadWork=0.7;    -- коофицент времени выполнения задания под действием лимонада.     
        drink_speed_bonus = 1.7;
        lemonad_time = 10;
        -- Дальше описаны параметры логики игры, менять их настоятельно не рекомендуется
        group=1;
        timerTask=-1;
        bonus_it = 0;
        GridData = { 1 };
        idle_timer = { 3, 8, 10 }; -- первый и второй параметр это границы таймера третий - добавка при вызове в том же цикле простоя к таймеру
        idle_animation = { 100, 100, 100, 100 }; --вероятности появления анимаций, их кол-во равно кол-ву анимаций простоя обьекта
        home = false;       -- do not change this parameter
        enabled = 0;        -- do not change this parameter(признак доступности клика)
        independence = 1;   -- do not change this parameter(признак получения пакета)
        --RandomTasks = 0;    -- do not change this parameter(отключить самодобавление задачи)
    };
    --точки контакта с другими
    ActivePoints = { 
        talk = { 
                   { {}, 1,1,0,  0,  1,1,0 };
                   }; 
    };
    --точки только для сына
    InnerPoint = {
        aaa = { {10,-3}, {10,0} };  --точки пугания
        telephon = { 13, -3}; --точка выноса телефона
        home = { 8, -2 };
    };
    Objects = {};
    -- list of all tasks for an object
    -- параметр 'timer' пределяет сколько будет выполнятся задача
    Tasks = { 
        endpath   = { FuncName="endPathExecute", timer = 1,  time_tick=30, hand_add=1 }; 
        awake = { FuncName="awakeExecute", timer = 2,  time_tick=1000, hand_add=1 }; 
        hide    = { FuncName="hideExecute", timer = 2,  time_tick=1000, hand_add=1 }; 
        talk = { FuncName="TalkTaskExecute",  skill_up = 0, not_need_action=1, hand_add=1 };  
        finish_talk = { FuncName="FinishTalkExecute",  time_tick=20, timer=1, hand_add=1 };   
        --lift_handset = { FuncName="LiftHandsetExecute",  time_tick=20, timer=1, hand_add=1 };  
        fill_lemonad = { FuncName="FillExecute", timer = {1}, hand_add=1 };
        br_plank_henhouse = {FuncName="PlankHenhouseExecute", timer = 3, time_tick=1000  }; --not_need_action=1
        br_plank_cowshed = {FuncName="PlankCowshedExecute", timer = 1, time_tick=1000  }; --not_need_action=1
        br_plank_goathouse = {FuncName="PlankGoathouseExecute", timer = 1, time_tick=1000  }; --not_need_action=1
        br_plank_sheephouse = {FuncName="PlankSheephouseExecute", timer = 1, time_tick=1000  }; --not_need_action=1
    };
-- Дальше описаны параметры и скрипты логики игры, менять их настоятельно не рекомендуется
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    -- list of all triggers for an object
    Triggers = {
        timerTrigger = {FuncName="TimerTriger", NotRunWhen={"awake","hide"}, cur_value=0 };    
        --drink_triger = {FuncName="DrinkTriger"};            
        --TalkTelephone = { FuncName="TalkTelephoneTriger",NotRunWhen={}, timer={ 35,45 }, first_timer={ 10,32 }, cur_value=0 };       
    };
    --tasks to be performed after an object is created
    InitActiveTasks = {}; 
    --tasks an object is waiting ofr after it is created
    InitExpectedTasks = {};
    task_buffer = {
        aaa = 0;
        mobila = 0;
        lemonad = 0;
    };
};

--состояния сына
stHOME = 0; --в доме
stAWAKE = 2; --появление
stGO_TELEPHON = 3; --идет на точку для телефона
stGO_AAA = 4; --бегать и пугать
stGO_LEMONAD = 5; --нести лимонад
stGO_OTHER = 6; --идти чинить забор
stTELEPHON = 7; -- стоять с телефоном
stLEMONAD = 8; --наливать лимонад
stOTHER = 9; --чинить забор
stAAA = 10; --пугать
stGO_HOME = 11; --идти к дому
stHIDE = 12; --исчезание
stMUST_GO_HOME = 14; --надо в дом
--глобальные задачи - подзадачи сидят в task
taskNONE = 0;
taskAAA = 1;
taskLEMONAD = 2;
taskTELEPHON = 3;
taskOTHER = 4;  --стандартные задачи 

iState = stHOME;
iCurTask = taskNONE;
iNextTask = taskNONE;
iTaskTimer = 0;
iMustSleep = 0;
iTaskMustFinish = 0;
-- возвращает обект
function GameObject:Get()
    return self;
end
-- возвращает параметры обьекта
function GetParams()
    aObj = GameObject:Get();   
    return aObj.Params;
end
-- может ли быть выполнен таск с идентификатаром
function isMayByTask(aTask)
    return 1;
end

function OnInit()
    aObj = GameObject:Get();
    --CPP_SetAnimState("normal");
    CPP_SetVisible(0);
    iState = stHOME;
    iCurTask = taskNONE;
    iNextTask = taskNONE;
    aObj.Params.ind_p_aaa = 1;
    aObj.Params.max_ind_p_aaa = table.getn(aObj.InnerPoint.aaa);
    iTaskTimer = 0;
    iMustSleep = 0;
    iTaskMustFinish = 0;
    aObj.Params.enabled = 0;
end

-- обработчик окончания выполнения задачи
function OnEndTask(aName, aTask)
    aObj = GameObject:Get();   
end

function endPathExecute()
    return 0;
end

function StartTask(aTask)
    if (iMustSleep == 1) then return; end
--ScriptDump("BEG: iNextTask="..iNextTask.."  iCurTask="..iCurTask.."   iTaskMustFinish="..iTaskMustFinish);
    if (iCurTask ~= taskNONE and iNextTask == taskNONE) then
--ScriptDump("StartTask1="..aTask);
        iNextTask = aTask;
        if (iCurTask == taskAAA) then
            iTaskMustFinish = 1;
        end
    else
        if (iCurTask == taskNONE) then
            iCurTask = aTask;
            iTaskTimer = 0;
            iTaskMustFinish = 0;
            OnStartTask(aTask);
        end
    end
--ScriptDump("END: iNextTask="..iNextTask.."  iCurTask="..iCurTask.."   iTaskMustFinish="..iTaskMustFinish);
end

function OnStartTask(aTask)
    iTaskTimer = 0;
    iCurTask = aTask;
    --iNextTask = taskNONE;
    iTaskMustFinish = 0;
end

function FinishTask()
    if (iMustSleep == 1) then return; end
--ScriptDump("0: iNextTask="..iNextTask.."  iCurTask="..iCurTask.."   iTaskMustFinish="..iTaskMustFinish);
    iCurTask = iNextTask;
    iNextTask = taskNONE;
    if (iCurTask ~= taskNONE) then
        aObj = GameObject:Get();
        if (iCurTask == taskAAA) then
            if (aObj.task_buffer.mobila > 0) then
                iCurTask = taskTELEPHON;
                iNextTask = taskAAA;
            else
                if (aObj.task_buffer.lemonad > 0) then
                    iCurTask = taskLEMONAD;
                    iNextTask = taskAAA;
                end
            end
        else
            if (aObj.task_buffer.mobila > 0) then
                iNextTask = taskTELEPHON;
            else
                if (aObj.task_buffer.lemonad > 0) then
                    iNextTask = taskLEMONAD;
                else
                    if (aObj.task_buffer.aaa > 0) then
                        iNextTask = taskAAA;
                    end
                end
            end
            if (iNextTask == iCurTask) then
                iNextTask = taskNONE;
            end
        end
        OnStartTask(iCurTask);
--ScriptDump("1: iNextTask="..iNextTask.."  iCurTask="..iCurTask.."   iTaskMustFinish="..iTaskMustFinish);
        return 1;
    else
        aObj = GameObject:Get();
        if (aObj.task_buffer.mobila > 0) then
            iCurTask = taskTELEPHON;
        else
            if (aObj.task_buffer.lemonad > 0) then
                iCurTask = taskLEMONAD;
            else
                if (aObj.task_buffer.aaa > 0) then
                    iCurTask = taskAAA;
                end
            end
        end
        if (iCurTask ~= taskNONE) then
            OnStartTask(iCurTask);
--ScriptDump("2: iNextTask="..iNextTask.."  iCurTask="..iCurTask.."   iTaskMustFinish="..iTaskMustFinish);
            return 1;
        end
    end
--ScriptDump("3: iNextTask="..iNextTask.."  iCurTask="..iCurTask.."   iTaskMustFinish="..iTaskMustFinish);
    return 0;
end

function TimerAAA()
    iTaskTimer = iTaskTimer + 1;
    if (iState == stHOME) then 
        SetState(stAWAKE);
    else
        SetState(stGO_AAA);
    end
    if (iState == stMUST_GO_HOME) then
        SetState(stGO_HOME);
    end
end

function TimerTelephon()
    iTaskTimer = iTaskTimer + 1;
    if (iState == stMUST_GO_HOME) then
--ScriptDump("LiftHandsetExecute");
        CPP_RunStringChild("mobila","TalkLeft();");
        NeedMobila(0);
        iTaskMustFinish = 1;
        SetState(stGO_HOME);
    end
    if (iState == stHIDE) then 
        SetState(stHOME);
        return;
    end
    if (iState == stHOME) then 
        SetState(stAWAKE);
        return;
    end
    if (iState == stAWAKE) then 
        SetState(stGO_TELEPHON);
        return;
    end
end
function TimerLemonad()
    iTaskTimer = iTaskTimer + 1;
    if (iState == stHIDE) then 
        SetState(stHOME);
        return;
    end
    if (iState == stHOME) then 
        SetState(stAWAKE);
        return;
    end
    if (iState == stAWAKE) then 
        SetState(stGO_LEMONAD);
        return;
    end
    if (iState == stMUST_GO_HOME) then
        SetState(stGO_HOME);
    end
end

function TimerOther()
    if (iState == stMUST_GO_HOME) then
        SetState(stGO_HOME);
    end
end

function TimerTriger()
    aObj = GameObject:Get();
    aTrigger = GameObject.Triggers.timerTrigger;
    aTrigger.cur_value = aTrigger.cur_value + 1;
-- DEBUG
--[[
--]]    
-- END DEBUG    
    if (iCurTask == taskNONE) then 
        if (iState == stHOME) then
            local res = CheckPackageForMe("awake");
            if (res > 0) then  SetState(stOTHER); end
            return;
        end
        if (iState == stMUST_GO_HOME) then
            SetState(stGO_HOME);
        end
        return; 
    end
    if (iCurTask == taskAAA) then
        return TimerAAA();
    end
    if (iCurTask == taskTELEPHON) then
        return TimerTelephon();
    end
    if (iCurTask == taskLEMONAD) then
        return TimerLemonad();
    end
    if (iCurTask == taskOTHER) then
        TimerOther();
    end
end

function awakeExecute()
    aObj = GameObject:Get();
    local tTask = aObj.Params.timerTask;
    local task = aObj.Tasks.awake;
    if (tTask < 0) then 
        tTask = task.timer; 
        CPP_SetVisible(1);
        CPP_SetAnimState("normal");
        CPP_SetAnimState("awakening_left_stand");
    end
    tTask = tTask - 1;
    aObj.Params.timerTask = tTask;
    if (tTask <= 0) then
        aObj.Params.timerTask = -1;
        return 0;
    end
    return 1;
end

function hideExecute()
    aObj = GameObject:Get();
    local tTask = aObj.Params.timerTask;
    local task = aObj.Tasks.hide;
    if (tTask < 0) then 
        tTask = task.timer; 
        CPP_SetAnimState("left_sleep_end");
    end
    tTask = tTask - 1;
    aObj.Params.timerTask = tTask;
    if (tTask <= 0) then
        SetState(stHOME);
        CPP_SetVisible(0);
--ScriptDump("hide!");    
        
        if (iMustSleep == 1) then
            iCurTask = taskNONE;
            iNextTask = taskNONE;
            CPP_Sleep(10000,1);
        end
        aObj.Params.timerTask = -1;
        return 0;
    end
    return 1;
end


function OnEndPath()
    aObj = GameObject:Get();
    aObj.Params.speed = aObj.Params.speed_normal;

    if (iState == stGO_HOME) then --идти к дому
        SetState(stHIDE);
        return;
    end
    if (iState == stGO_AAA or iState == stGO_TELEPHON) then --пугать или телефон
        StateNext = GetNextState();
--ScriptDump("iNextTask="..iNextTask.."  iCurTask="..iCurTask.."  StateNext="..StateNext.."   iTaskMustFinish="..iTaskMustFinish);
        SetState(StateNext);
        return;
    end
end

function SetState(aState)
    aObj = GameObject:Get();
    aObj.Params.enabled = 0;
    local iOldState = iState;
    iState = aState;
    if (iOldState == stGO_AAA and iState ~= stGO_AAA) then
        CPP_SetVisPrefix("");
    end
    if (iState == stHOME) then --в доме
        if (iTaskMustFinish == 1) then
            FinishTask();
        end
        CPP_SetVisible(0);   --в hide уже заложено
        return;
    end
    if (iState == stAWAKE) then --появление
        CPP_SetVisible(1);
        CPP_SetAnimState("normal");
        CPP_DoTaskIfPossible("awake","");  return;
    end
    if (iState == stGO_TELEPHON) then --идет на точку для телефона
        CPP_SetVisPrefix("");
        local x = aObj.InnerPoint.telephon[1];
        local y = aObj.InnerPoint.telephon[2];
        Go(x,y);
        return;
    end
    if (iState == stGO_AAA) then --бегать и пугать
        local point = aObj.InnerPoint.aaa[aObj.Params.ind_p_aaa];
        local x = point[1];
        local y = point[2];
        CPP_SetVisPrefix("aaa");
        Go(x,y);
        aObj.Params.ind_p_aaa = aObj.Params.ind_p_aaa + 1;
        if (aObj.Params.ind_p_aaa > aObj.Params.max_ind_p_aaa) then 
            aObj.Params.ind_p_aaa = 1;
        end
        return;
    end
    if (iState == stGO_LEMONAD) then --нести лимонад
        CPP_SetVisPrefix("lem");
        CPP_OtherObjAddExpectedTasks("lemonad","fill",0);
        CPP_OnTrigger("fill",1);
        return;
    end
    if (iState == stTELEPHON) then -- стоять с телефоном
        --CPP_SetVisPrefix("phone");
        CPP_SetAnimState("right_stand_phone");
        aObj.Params.enabled = 1;
        CPP_PutOnTopExpectedTasks("talk");
        CPP_WantSelect(1);
        CPP_PlaySound("telephone_ring",1);
        return;
    end
    if (iState == stLEMONAD) then --наливать лимонад
        return;
    end
    if (iState == stOTHER) then --стандартные задачи
        iCurTask = taskOTHER;
        return;
    end
    if (iState == stAAA) then --пугать
        return;
    end
    if (iState == stGO_HOME) then --идти к дому
        local x = aObj.InnerPoint.home[1];
        local y = aObj.InnerPoint.home[2];
        Go(x,y);
        return;
    end
    if (iState == stHIDE) then --исчезание
        CPP_DoTaskIfPossible("hide","");    return;
    end
end

function GetNextState()
    aObj = GameObject:Get();
    if (iMustSleep == 1) then 
        iCurTask = taskNONE;
        iNextTask = taskNONE;
        return stGO_HOME;
    end
    if (iCurTask == taskAAA) then
        if (iNextTask == taskNONE) then
            if (iTaskMustFinish == 1) then  return stGO_HOME; end
            local res = CheckPackageForMe("");
            if (res > 0) then  return stOTHER; end
            return stGO_AAA;
        else
            if (iNextTask == taskTELEPHON) then
                local old = aObj.task_buffer.mobila;
                FinishTask();
                aObj.task_buffer.mobila = old;
                --OnStartTask(taskTELEPHON);
                return stGO_HOME;
            end
            if (iNextTask == taskLEMONAD) then
                local old = aObj.task_buffer.lemonad;
                FinishTask();
                aObj.task_buffer.lemonad = old;
                --OnStartTask(taskLEMONAD);
                return stGO_HOME;
            end
        end
        return stHIDE;
    end
    if (iCurTask == stGO_TELEPHON) then
        if (iTaskMustFinish == 1) then return stGO_HOME; end
        return stTELEPHON;
    end
    if (iCurTask == stGO_LEMONAD) then
        if (iTaskMustFinish == 1) then return stGO_HOME; end
        return stGO_LEMONAD;
    end
    return stHIDE;
end

function Go(aX,aY)
    aObj = GameObject:Get();
    if (iState == stGO_AAA) then
        aObj.Params.speed = aObj.Params.speed_aaa;
    else
        aObj.Params.speed = aObj.Params.speed_normal;
    end
    GoToPoint(aX,aY,"OnEndPath();");    
end

function SleepOnEnd()
    if (iMustSleep == 0) then
        aObj.Params.enabled = 0;
        iMustSleep = 1;
        CPP_WantSelect(0);
        CPP_StopSound("telephone_ring");
        if (iState == stHOME or iState == stAWAKE) then --в доме
            CPP_SetVisible(0);
            CPP_Sleep(10000,1);
            return;
        end
        if (iState == stGO_TELEPHON) then --идет на точку для телефона
            return;
        end
        if (iState == stGO_AAA) then --бегать и пугать
            return;
        end
        if (iState == stTELEPHON) then -- стоять с телефоном
            SetState(stGO_HOME);
            return;
        end
        
        
        if (iState == stGO_LEMONAD) then --нести лимонад
            return;
        end
        if (iState == stGO_OTHER) then --идти чинить забор
            return;
        end
        if (iState == stLEMONAD) then --наливать лимонад
            return;
        end
        if (iState == stOTHER) then --чинить забор
            return;
        end
        if (iState == stAAA) then --пугать
            return;
        end
        if (iState == stGO_HOME) then --идти к дому
            return;
        end
        if (iState == stHIDE) then --исчезание
            return;
        end
--[[        
        if (iState == )
            SetState(stGO_HOME);
        end
--]]        
    end
end

function TalkTaskExecute()
    aObj = GameObject:Get();
    -- мы подняли трубку и получили заказ
    CPP_RecursiveRun("telephone_order",0);
    return 0;
end

function LiftHandsetExecute()
    SetState(stMUST_GO_HOME);
    return 0;
end

function FinishTalkExecute()
--ScriptDump("FinishTalkExecute");    
    CPP_SetAnimState("left_stand");
    CPP_StopSound("telephone_ring");
    return 0;
end

function NeedAAA(aNeed)
    aObj = GameObject:Get();
    if (aNeed > 0) then
        aObj.task_buffer.aaa = aObj.task_buffer.aaa + 1;
        StartTask(taskAAA);
    else
        aObj.task_buffer.aaa = aObj.task_buffer.aaa - 1;
        if (aObj.task_buffer.aaa <= 0) then
            aObj.task_buffer.aaa = 0;
            if (iCurTask == taskAAA) then
                iTaskMustFinish = 1;
            end
            if (iNextTask == taskAAA) then
                iNextTask = taskNONE;
            end
        end
    end
end
function NeedMobila(aNeed)
    aObj = GameObject:Get();
    if (aNeed > 0) then
        aObj.task_buffer.mobila = 1;
        StartTask(taskTELEPHON);
    else
        aObj.task_buffer.mobila = 0;
    end
--ScriptDump("MOBILA:aNeed="..aNeed);
end
function NeedLemonad(aNeed)
    aObj = GameObject:Get();
    if (aNeed > 0) then
        aObj.task_buffer.lemonad = 1;
        StartTask(taskLEMONAD);
    else
        aObj.task_buffer.lemonad = 0;
    end
end

function FillExecute()
    CPP_SetVisPrefix("");
    return 0;
end
function OnEndFillExecute()
    aObj = GameObject:Get();
    NeedLemonad(0);
    iTaskMustFinish = 1;
    SetState(stMUST_GO_HOME);
    return 0;
end
-- добавить в конец любой стандартной задачи по обслуживанию обьектов(например забора)
-- эти задачи выгребаются из очереди пакетов
function OnOtherTaskFinished()
    iTaskMustFinish = 1;
    SetState(stMUST_GO_HOME);
end

function PlankHenhouseExecute()
    aObject = GameObject:Get();
    local tTask = aObject.Params.timerTask;
    if (tTask < 0) then 
        tTask = aObject.Tasks.br_plank_henhouse.timer; 
    end
    tTask = tTask - 1;
    aObject.Params.timerTask = tTask;
    if (tTask <= 0) then
        aObject.Params.timerTask = -1;
        OnOtherTaskFinished();
        return 0;
    end
    return 1;
end

function PlankCowshedExecute()
    aObject = GameObject:Get();
    local tTask = aObject.Params.timerTask;
    if (tTask < 0) then 
        tTask = aObject.Tasks.br_plank_cowshed.timer; 
    end
    tTask = tTask - 1;
    aObject.Params.timerTask = tTask;
    if (tTask <= 0) then
        aObject.Params.timerTask = -1;
        OnOtherTaskFinished();
        return 0;
    end
    return 1;
end

function PlankGoathouseExecute()
    aObject = GameObject:Get();
    local tTask = aObject.Params.timerTask;
    if (tTask < 0) then 
        tTask = aObject.Tasks.br_plank_goathouse.timer; 
    end
    tTask = tTask - 1;
    aObject.Params.timerTask = tTask;
    if (tTask <= 0) then
        aObject.Params.timerTask = -1;
        OnOtherTaskFinished();
        return 0;
    end
    return 1;
end

function PlankSheephouseExecute()
    aObject = GameObject:Get();
    local tTask = aObject.Params.timerTask;
    if (tTask < 0) then 
        tTask = aObject.Tasks.br_plank_sheephouse.timer; 
    end
    tTask = tTask - 1;
    aObject.Params.timerTask = tTask;
    if (tTask <= 0) then
        aObject.Params.timerTask = -1;
        OnOtherTaskFinished();
        return 0;
    end
    return 1;
end

-- не удалять используется в брате
function RestoreAfterTrashIfAsObj()
    if (iState == stTELEPHON) then -- стоять с телефоном
        aObj = GameObject:Get();
        aObj.Params.enabled = 1;
        CPP_WantSelect(1);
        --CPP_PlaySound("telephone_ring",1);
    end
end
