-- write out that we loaded sucessfully (mor or less, anyway)
io.write("Starting script for Level: Desert 3 (16) in BlinkenLUA / ",_VERSION,"!\n")
bs.callback.engine.init("initLevel");


-- sign-switches and doors
--      (sry - I'm unable to translate the following line to english... pls do so if u can!)
--   9 Switches, die zusammen ein Bild ergeben wie in klein bei fg_sign_X.png zu sehen ist, angeordnet wie folgt:
--    7 8 9
--    4 5 6
--    1 2 3
--   (just like the num-pad on your keyboard usually)

OBJ_SIGN_SWITCH = {};
STATUS_SIGN_SWITCH = {};
--   STATUS_SIGN_SWITCH[ Switch 1..9 ]: 0 = red/off, 1 = green/on(default)

for i=1,9 do
    OBJ_SIGN_SWITCH[i] = -1;
    STATUS_SIGN_SWITCH[i] = 1;
end
-- --Config-- How many "Sign-Doors" are there overall?
COUNT_SIGN_DOORS=5;
-- -- End of Config --

CFG_SIGN_DOORS_SWITCH_VALUE = {};
for d = 1,COUNT_SIGN_DOORS do
    CFG_SIGN_DOORS_SWITCH_VALUE[d] = {};
    for s = 1,9 do
        CFG_SIGN_DOORS_SWITCH_VALUE[d][s]=0;
    end
end

-- --Config-- defines the required "code" needed for each door to be opend
--   CFG_SIGN_DOORS_SWITCH_VALUE[ Door 1..COUNT_SIGN_DOORS ][ Switch 1..9 ] = VALUE;
--    where VALUE is one off: 0=may be red or green(default), 1=must be red, 2=must be green
--   Example: If only the following line exists for door Nr 1, then the only
--    precondition to open door Nr 1 is that Switch Nr 9 (upper right corner) has
--    to be red. All other Switches may be red or green.
--     CFG_SIGN_DOORS_SWITCH_VALUE[1][9] = 1;

-- f
CFG_SIGN_DOORS_SWITCH_VALUE[1][2] = 1;
CFG_SIGN_DOORS_SWITCH_VALUE[1][3] = 1;
CFG_SIGN_DOORS_SWITCH_VALUE[1][5] = 1;
CFG_SIGN_DOORS_SWITCH_VALUE[1][6] = 1;
CFG_SIGN_DOORS_SWITCH_VALUE[1][8] = 2;
CFG_SIGN_DOORS_SWITCH_VALUE[1][9] = 1;

-- h
CFG_SIGN_DOORS_SWITCH_VALUE[2][1] = 1;
CFG_SIGN_DOORS_SWITCH_VALUE[2][2] = 2;
CFG_SIGN_DOORS_SWITCH_VALUE[2][3] = 2;

-- i
CFG_SIGN_DOORS_SWITCH_VALUE[3][1] = 2;
CFG_SIGN_DOORS_SWITCH_VALUE[3][2] = 1;
CFG_SIGN_DOORS_SWITCH_VALUE[3][3] = 2;

-- l
CFG_SIGN_DOORS_SWITCH_VALUE[4][1] = 1;
CFG_SIGN_DOORS_SWITCH_VALUE[4][7] = 2;

-- n
CFG_SIGN_DOORS_SWITCH_VALUE[5][7] = 1;
CFG_SIGN_DOORS_SWITCH_VALUE[5][8] = 1;
CFG_SIGN_DOORS_SWITCH_VALUE[5][9] = 2;


-- -- End of Config --

GFX_SIGN_DOOR = {};
OBJ_SIGN_DOOR = {};

--   STATUS_SIGN_DOOR[ Door 1..COUNT_SIGN_DOORS ]: 0 = closed(default), 1 = open
STATUS_SIGN_DOOR = {};

for i=1,COUNT_SIGN_DOORS do
    STATUS_SIGN_DOOR[i]=0;
end

-- elevators
Y_KORREKTUR=0;
X_KORREKTUR=0;

-- --Config-- How many Elevators are there overall?
COUNT_ELEVATORS = 1;
-- -- End of Config --
-- --Config-- Where should they be (permanet x-coord, min and max y-coord, start y-coord, how fast, ..
CFG_ELEVATOR_VALUES_X = { 3280 };
CFG_ELEVATOR_VALUES_Y_MIN = { 730 };
CFG_ELEVATOR_VALUES_Y_MAX = { 1050 };
CFG_ELEVATOR_VALUES_Y_POS = { 900 };
CFG_ELEVATOR_VALUES_DIR = { 1 };
CFG_ELEVATOR_VALUES_BLINK_ON = { 2 };
CFG_ELEVATOR_VALUES_BLINK_OFF = { 1 };
-- -- End of Config --

BLINKEN_TIMER = 0;
GFX_ELEVATOR = {};
OBJ_ELEVATOR = {};




-- Required function: Initializing the level
function initLevel ()

   
    -- create special bg
    --    Load gfx
    GFX_SPECIAL_BG = bs.gfx.load("fg_desertcave_desertbg.jpg");
   
    for i=0,8 do
        OBJ_SPECIAL_BG = bs.obj.new(i*18*32, 0, GFX_SPECIAL_BG, "visible");
    end
    
    -- create sign-switches
    --    Load gfx
    GFX_SIGN_SWITCH_RED = bs.gfx.load("fg_sign_switch_red.png");
    GFX_SIGN_SWITCH_GREEN = bs.gfx.load("fg_sign_switch_green.png");
    
    --    Add Objects
    tmp_y=15;
    for j=0,2 do
        tmp_x=54;
        for i=1,3 do
            OBJ_SIGN_SWITCH[i+(j*3)] = bs.obj.new(tmp_x*32, tmp_y*32, GFX_SIGN_SWITCH_GREEN, "visible");
            OBJ_SIGN_SWITCH[i+(j*3)].callback.playeraction("handleSwitchAction");
            STATUS_SIGN_SWITCH[i+(j*3)] = 1;
            tmp_x=tmp_x+2;
        end
        tmp_y=tmp_y-2;
    end
        
    
    -- create sign-doors
    --   Load gfx, Add Objects
    initSignDoor(1, "fg_sign_f.png", 101, 18);
    initSignDoor(2, "fg_sign_h.png", 62, 25);
    initSignDoor(3, "fg_sign_i.png", 74, 22);
    initSignDoor(4, "fg_sign_l.png", 68, 17);
    initSignDoor(5, "fg_sign_n.png", 47, 17);
    
    
    -- load extra sound
    SND_DOOR_OPEN = bs.snd.load("fx_open_door.ogg");
    SND_DOOR_CLOSED = bs.snd.load("fx_close_door.ogg");
    SND_SIGN_SWITCH_ON = bs.snd.load("fx_altemark__bd4.wav");
    SND_SIGN_SWITCH_OFF = bs.snd.load("fx_altemark__bd5.wav");

   
    -- Create elevators
    --    Load gfx
    GFX_ELEVATOR[1] = bs.gfx.load("elevator2.bmp");
    GFX_ELEVATOR[2] = bs.gfx.load("elevator1.bmp");
    
    --    Add Objects
    for i=1,COUNT_ELEVATORS do
        OBJ_ELEVATOR[i] = bs.obj.new(43, 22, GFX_ELEVATOR[1], "visible,blocking,elevator");
    end
   
   bs.callback.engine.physics("scriptPhysics");
end




-- Required function: Physics-loop for scripting part
function scriptPhysics ()
    
    -- Elevator + SwitchDoor display
    BLINKEN_TIMER = BLINKEN_TIMER + 1;
    if BLINKEN_TIMER == 30 or BLINKEN_TIMER == 105 then
        for i=1,COUNT_SIGN_DOORS do
            OBJ_SIGN_DOOR[i].visible(bs.yes);
        end
    end
    if BLINKEN_TIMER == 55 or BLINKEN_TIMER == 130 then
        for i=1,COUNT_SIGN_DOORS do
            if STATUS_SIGN_DOOR[i]  == 1 then
                OBJ_SIGN_DOOR[i].visible(bs.no);
            end
        end
    end
    if BLINKEN_TIMER == 50 then
        for i=1,COUNT_ELEVATORS do
            OBJ_ELEVATOR[i].gfx(GFX_ELEVATOR[CFG_ELEVATOR_VALUES_BLINK_ON[i]]);
        end
    end
    if BLINKEN_TIMER > 150 then
        for i=1,COUNT_ELEVATORS do
            OBJ_ELEVATOR[i].gfx(GFX_ELEVATOR[CFG_ELEVATOR_VALUES_BLINK_OFF[i]]);
        end
        BLINKEN_TIMER = 0;
    end

    
    -- Elevator physics
    for i=1,COUNT_ELEVATORS do    
        CFG_ELEVATOR_VALUES_Y_POS[i] = CFG_ELEVATOR_VALUES_Y_POS[i] + CFG_ELEVATOR_VALUES_DIR[i];
        if CFG_ELEVATOR_VALUES_Y_POS[i] < CFG_ELEVATOR_VALUES_Y_MIN[i]+1 or CFG_ELEVATOR_VALUES_Y_POS[i] > CFG_ELEVATOR_VALUES_Y_MAX[i]-1 then
            CFG_ELEVATOR_VALUES_DIR[i] = CFG_ELEVATOR_VALUES_DIR[i] * -1;
        end
        OBJ_ELEVATOR[i].x(CFG_ELEVATOR_VALUES_X[i]);
        OBJ_ELEVATOR[i].y(CFG_ELEVATOR_VALUES_Y_POS[i]);
    end
    
end




-- Required function: Callback on "Action"-Button on FG-Objects
function handleSwitchAction (obj_id)
    -- Handle sign-switches
    for i=1,9 do
        if obj_id.x() == OBJ_SIGN_SWITCH[i].x() and obj_id.y() == OBJ_SIGN_SWITCH[i].y() then
            handleSignDoor(i);
        end
    end

end







-- Script-internal functions

function initSignDoor(obj_nr, file, x, y)
--     Loads gfx and adds Object at given position ans with app. porp's (blocking, visible, onTop, not killin)
--   Parameter:
--    obj_nr is the Number of the door
--    file is a String with the filename of the gfx-file
--    x and y describe the position of the door (counted in BlinkenPixels(32 real Pixels per one BlinkenPixel), not in real Pixels)
--   Return:
--    nothing
    GFX_SIGN_DOOR[obj_nr] = bs.gfx.load(file);
    OBJ_SIGN_DOOR[obj_nr] = bs.obj.new(x*32, y*32, GFX_SIGN_DOOR[obj_nr], "visible,blocking,ontop");
end




function handleSignDoor(i)
--   called by the required callback handleAction when Switch i ( 1..9 ) is "pushed"
--    toggles the status off the switch (0=red/off, 1=green/on(default)
--    sets the app. picture for the switch
--    and calls handleSignDoorRaetsel(), which checks, if doors have to be opend or closes due to the new switch-status
--   Parameter:
--    i is the Number of the switch that just has been pushed ( 1..9 )
--   Return:
--    nothing
    if STATUS_SIGN_SWITCH[i] == 0 then
        SND_SIGN_SWITCH_ON.play();
        OBJ_SIGN_SWITCH[i].gfx(GFX_SIGN_SWITCH_GREEN);
        STATUS_SIGN_SWITCH[i] = 1;
    else
        SND_SIGN_SWITCH_OFF.play();
        OBJ_SIGN_SWITCH[i].gfx(GFX_SIGN_SWITCH_RED);
        STATUS_SIGN_SWITCH[i] = 0;
    end
    handleSignDoorRaetsel();
end




function handleSignDoorRaetsel()
--      calles by handleSignDoor(i), this fkt checks, if doors have to be opend or closes
--       reds status of all 9 switches and all Doors an decides, based on the information
--       in the config-array CFG_SIGN_DOORS_SWITCH_VALUE, if there is a door that have
--       to be opend or closed now.
    play_sound = 3;
    
    --   for each door check if it has to be opend or closed
    for d = 1,COUNT_SIGN_DOORS do
        --   first default to "yes, the door has to be open"
        boolean_activte_door = 1;
        for s = 1,9 do
                if CFG_SIGN_DOORS_SWITCH_VALUE[d][s] > 0 then
                    if STATUS_SIGN_SWITCH[s] == CFG_SIGN_DOORS_SWITCH_VALUE[d][s] -1 then
                    else    
                        --   if at least one switch is in the wrong status for the door-code, the door must not be open!
                        boolean_activte_door = 0;
                    end
                end
        end
        if boolean_activte_door > 0 then
            if STATUS_SIGN_DOOR[d] == 0 then
                --   if the door should be open, but isn't, then open it now
                play_sound = minimum(setSwitchDoorOpenOrClosed(d, 1), play_sound);
            end
        else
            if STATUS_SIGN_DOOR[d] == 1 then
                --   if the door should be closed, but isn't, then close it now
                play_sound = minimum(setSwitchDoorOpenOrClosed(d, 0), play_sound);
            end
        end
    end

--     play_sound=3: play no sound here at end of fkt,
--      1: play sound "door open" here at end of fkt,
--      2: play sound "door closed" here at end of fkt    
    if play_sound == 1 then
        SND_DOOR_OPEN.play();
    end
    if play_sound == 2 then
        SND_DOOR_CLOSED.play();
    end
end




function minimum(a, b)
--   returns the smaller number
--   Parameter:
--    a and b are numbers
--   Returns: a if a<b, else b
    if a < b then
        return a;
    else
        return b;
    end
end




function setSwitchDoorOpenOrClosed(obj_nr, openOrNot)
--   called by handleSignDoorRaetsel(), this fkt opens or closes a door
--    Sets door-status (0=closed, 1=open) and if the door should be blocking, visible and onTop
--   Parameter:
--    obj_nr is the Number of the door that will be opend or closed,
--    openOrNot is 1 for "open door now" or 0 for "please close that door now"
--   Returns: "play_sound"-code, used in handleSignDoorRaetsel() to know, what kind of
--    sound should be played at end of fkt handleSignDoorRaetsel() (1: play sound "door open", 2: play sound "door closed")
    STATUS_SIGN_DOOR[obj_nr]  = openOrNot;
    if openOrNot == 0 then
    	OBJ_SIGN_DOOR[obj_nr].blocking(bs.yes);
    	OBJ_SIGN_DOOR[obj_nr].visible(bs.yes);
    	OBJ_SIGN_DOOR[obj_nr].ontop(bs.yes);
    else
    	OBJ_SIGN_DOOR[obj_nr].blocking(bs.no);
    	OBJ_SIGN_DOOR[obj_nr].visible(bs.no);
    	OBJ_SIGN_DOOR[obj_nr].ontop(bs.no);
    end
    return 2-openOrNot;
end
