cxr2 = arcade_config.character_per_row_base2

-- 4, 3

-- imp={hab=75,
--      x=24,
--      y=24,
--      w=32,
--      h=32,
--      flip=true,
--      enabled=false,
--      counter=500,
--      frame=28,
--      wait=0,
--      step=0,
--      anim={28,29,28,30},
--      bb={x=4,y=0,w=16,h=32},
--      scene_intro=false,
--      scene_object=false,
--      fight_modes={"chase","away","super","shot"},
--      mode="stop",
--      mode_cooldown=100}

imp = {}

function imp.reset()
    imp.hit=imp.hit
    imp.update=imp.update
    imp.draw=imp.draw
    imp.hab=abad.hab
    imp.enabled=false
    imp.counter=500
end

function imp.new(_hab, _x, _y)
    local world_x, world_y = coords.room_to_world(_hab,_x,_y)
    _fight_modes={"chase","away","super","shot"}
    for i,v in ipairs(_fight_modes) do _fight_modes[v] = i end
    return { name="imp",
       hab=_hab,
       x=world_x, y=world_y,
       w=32, h=32,
       flip=true, 
       frame=28,
       wait=0,
       vides=1,
       energia=6,
       max_energia=6,
       falling=0,
       step=0,
       hurting=0,
       jumpfwd=false,
       step_length=1,
       vmove_space=1,
       max_jump_height=24,
       jump_height=0,
       jump_in_half_block=0,
       jump_in_half_block_used = false,
       max_shoot_cooldown=24,
       shot_power=1,
       shot_num_shots=1,
       shoot_cooldown=25,
       anim={28,29,28,30},
       bb={x=8,y=0,w=16,h=32},
       scene_intro=false,
       scene_object=false,
       fight_modes=_fight_modes,
       mode="stop",
       mode_cooldown=100,
       super_cooldown=2000,
       shot_cooldown=500,
       action="",
       fight=imp.fight,
       draw=imp.draw,
       hit=imp.hit,
       direccio=imp.direccio,
       do_jump=imp.do_jump,
       jump=imp.jump,
       state_jumping=imp.state_jumping,
       chase=imp.chase,
       away=imp.away,
       move=imp.move,
       super=imp.super,
       shot=imp.shot,
       do_flip=imp.do_flip,
       update=imp.state_normal,
       land=imp.land,
       mode_controller=imp.mode_controller,
       movement=imp.movement,
       advance=imp.advance,
       reduce_cooldown=imp.reduce_cooldown,
       -- imp.enabled=false
       -- imp.counter=500
    }
end

function imp:fight()
    print("FIGHTING MODE")
    self.mode="away"
end

function imp:draw()
    local scr_x, scr_y = viewp:screen_coords( self.x, self.y )
    draw.surf((self.frame&7)*self.w, (self.frame>>cxr2)*self.h, self.w, self.h, scr_x, scr_y, self.w, self.h, self.flip)
    draw.rect(scr_x+self.bb.x,scr_y+self.bb.y,self.bb.w,self.bb.h,3)
end

function imp:hit()
    --
end

function imp:direccio( actor )
msg_print(0,0,"direccio",true)
    local check_side = "L"
    -- definir el punts per a comprobar en el mapa
    if self.fight_modes[self.mode]=="away" then
        if actor.x>self.x then
            -- caminar cap "enrere", check costat esq
            check_side = "L"
        else
            -- caminar cap "endavant", check costat dret
            check_side = "R"
        end
    elseif self.fight_modes[self.mode]=="chase" then
        if actor.x>self.x then
            -- caminar cap "endavant", check costat dret
            check_side = "R"
        else
            -- caminar cap "enrere", check costat esq
            check_side = "L"
        end
    end
    
    local step = 1
    if check_side=="L" then step = -step end

    return step
end

function imp:do_jump ( jumpfwd )
msg_print(0,0,"do_jump",true)
    -- Inicialització de fer el salt
    jumpfwd = jumpfwd or false
    self.jump_height = 0
    self.update=imp.state_jumping
    self.step=0
    self.jumpfwd=jumpfwd
end

function imp:state_jumping()
    msg_print(0,0,"state_jumping",true)
    self:reduce_cooldown()
    -- ??
    self.wait=self.wait+1
    self.wait=0

    -- Pujar o caure
    if self.jump_height<self.max_jump_height then
        -- Comprovar que pasa en l'aire
        self:jump()
    else
        -- Canviar a mode caure
        self.update=imp.state_falling
    end
    self.step=self.step+1

    -- cap endavant?
    if self.jumpfwd then self:advance() end
end

function imp:jump()
msg_print(0,0,"jump",true)
    local vspace = self.vmove_space
    -- Els dos punts de dalt del personatge
    local x1_check = self.x+self.bb.x
    local x2_check = self.x+self.bb.x+self.bb.w
    local y_check = self.y-vspace; -- posicio de dalt
    
    -- Comprovar on està pegant
    local tile1_hit_type= arc_check_tile(x1_check, y_check )
    local tile2_hit_type= arc_check_tile(x2_check, y_check)
    local not_block_tile = tile1_hit_type ~= tiletype.block and tile2_hit_type ~= tiletype.block
    
    -- Fer l'acció que correspon
    if not_block_tile then
        -- Ascendir
        self.y=self.y-vspace
    else
        -- Si es un bloc permetre gastar l'espai no pintat
        local tile1_hit = arc_get_tile(x1_check, y_check )
        local tile2_hit = arc_get_tile(x2_check, y_check)
        local half_block1 = mapa_is_half_block_tile(map_to_editor_tile(tile1_hit))
        local half_block2 = mapa_is_half_block_tile(map_to_editor_tile(tile2_hit))
        local full_block1 = tile1_hit_type == tiletype.block and not half_block1
        local full_block2 = tile2_hit_type == tiletype.block and not half_block2
        local full_block = full_block1 and full_block2
        local half_block = half_block1 or half_block2
        -- Si ninguno dels tiles tocats es un block complet
        -- i almenys un dels tiles tocats es mig tile
        -- permetre continuar en el salt
        if not full_block and half_block then
            if self.jump_in_half_block==0 and not self.jump_in_half_block_used then
                self.jump_in_half_block = arcade_config.tiles_height / 2
            end
            if self.jump_in_half_block>0 then
                self.y=self.y-vspace
                self.jump_in_half_block = self.jump_in_half_block-1
                self.jump_in_half_block_used = true
            end
        end
    end
    
    -- Registrar el desplaçament
    self.jump_height = self.jump_height+1
end

function imp:state_walking()
msg_print(0,0,"state_walking",true)
    self:reduce_cooldown()

    -- Limitar la velocitat de moviment
    self.wait=self.wait+1

    -- representació del moviment
    -- if self.wait==6 then
    --     self.wait=0
    --     self.step=(self.step+1)%2
    --     self.frame=self.anim[self.step+1]        
    -- end
    
    -- Selecció de frame
    if self.wait==6 then
        self.wait=0
        self.step=(self.step+1)%4
        self.frame=self.anim[self.step+1]
    end
    
    -- Comprovar dos punts de contacte del personatge en el piso a vore si cau
    local x1_check = self.x+self.bb.x
    local x2_check = x1_check+self.bb.w
    local y_check = self.y+self.bb.h; -- base del personatge
    local tile1 = arc_check_tile(x1_check,y_check)
    local tile2 = arc_check_tile(x2_check,y_check)
    if tile1==tiletype.void and tile2==tiletype.void then
        -- si no hi ha piso, caure
        self.update=imp.state_falling
        return
    end
    
    self:advance()
    self:move()
end

function imp:state_falling()
msg_print(0,0,"state_falling",true)
    self:reduce_cooldown()

    -- print("state_falling")
    
    self.frame=30
    self.wait=self.wait+1
    
    -- Si toca terra canviar el mode
    if self:land() then
        self.update=imp.state_normal
        return
    end    
    
    -- Seguir caiguent
    self.y=self.y+1
    self.jump_height = self.jump_height-1
    self.falling=self.falling+1
    
    -- Caiguent cap endavant?
    if self.jumpfwd then self:advance() end
end

function imp:land ()
msg_print(0,0,"land",true)
    -- Els dos punts de baix de l'abad
    local x1_check = self.x+self.bb.x
    local x2_check = self.x+self.bb.x+self.bb.w
    local y_check = self.y+self.bb.h
    
    -- Comprovar on està aterrant
    local tile1_hit= arc_check_tile(x1_check, y_check )
    local tile2_hit= arc_check_tile(x2_check, y_check)
    local floor_tile = tile1_hit>=tiletype.half or tile2_hit>=tiletype.half
    
    -- Encara que siga un tile de piso s'ha de comprovar que 
    -- la y es un múltiple de l'alt dels tiles
    local over_tile = (y_check & 0xF) == 0 
    
    local can_land = floor_tile and over_tile
    
    if can_land then
        self.jump_in_half_block_used = false
        self.jump_height = 0
    end
    
    return can_land
end

function imp:advance()
msg_print(0,0,"advance",true)
    local step_length=self.step_length; --lo que avança l'abad cada pas
    local limit=tiletype.block
    
    if self.update~=imp.state_walking then limit=tiletype.half end

    local x_check = self.x+self.bb.x+self.bb.w+step_length
    -- if self.flip then 
        -- step_length = -step_length 
        -- x_check = self.x+self.bb.x+step_length
    -- end
    
    -- self.action=="right"
    if self.action=="left" then 
        step_length = -step_length 
        x_check = self.x+self.bb.x+step_length
    end
    
    local y_check = self.y+self.bb.h-4
    
    if arc_check_tile(x_check, y_check)<limit then
        self.x=self.x+step_length
    end

    local hab,xx, yy = coords.world_to_tile(self.x, self.y)
    self.hab = hab
end

-- Controlador principal del personatge
function imp:state_normal()
msg_print(0,0,"state_normal",true)
    self:reduce_cooldown()

    self.frame=28
    self.wait=0
    self.step=0
    self.jumpfwd=false
    self.jump_height = 0
    self:move()
end

function imp:chase()
    self.mode = self.fight_modes["chase"]
    self.mode_cooldown = 150+math.random(50)-1
end

function imp:away()
    self.mode = self.fight_modes["away"]
    self.mode_cooldown = 150+math.random(50)-1
end

function imp:super()
    self.mode = self.fight_modes["super"]
    self.mode_cooldown=1
    print("SUPER POWER")
    self.super_cooldown=2000
end

function imp:shot(actor)
    self.mode = self.fight_modes["shot"]
    self.mode_cooldown=1
    print("FIREBALL!!")
    self.shot_cooldown = 500
end

function imp:do_flip(actor)
    if actor.x<self.x then self.flip=true else self.flip=false end
end

function imp:move(abad)
msg_print(0,0,"move",true) 
    self:mode_controller()
    
    self.action = self:movement(abad)
    
    -- print(action)
    
    if self.action == "right" or self.action == "left" then
        self.update=imp.state_walking
        -- abad.flip=false
    elseif self.action == "jump" then
        self:do_jump()
    elseif self.action == "jumpfwd" then
        self:do_jump(true)
    elseif self.action == "shot" then
        -- abad_shot_cacau()
        self:shot()
    elseif self.action == "super" then
        self:super()
    end
end

function imp:movement( actor )
    local action = "stay"
    
    if self.mode=="stop" then return action end
    
    if self.fight_modes[self.mode]=="away" or self.fight_modes[self.mode]=="chase" then
        if self.y>abad.y 
           and arc_check_tile(self.x+(self.bb.x+(self.bb.w/2)),(self.y+(self.h/2)))~=tiletype.void then
            action = "jump"
        elseif self.y==abad.y and math.abs(self.x-abad.x)<=8 then
            action = "jumpfwd"
        else
            if self.fight_modes[self.mode]=="away" then
                if abad.x<self.x then 
                    action="right" 
                else
                    action="left"
                end
            elseif self.fight_modes[self.mode]=="chase" then
                if abad.x>self.x then 
                    action="right" 
                else
                    action="left"
                end
            end
        end
    elseif self.fight_modes[self.mode]=="super" then
        action="super"
    elseif self.fight_modes[self.mode]=="shot" then
        action="shot"
    end
    
    return action
end

function imp:reduce_cooldown()
    if self.mode=="stop" then return end
    
    self.mode_cooldown  = self.mode_cooldown  -1
    self.super_cooldown = self.super_cooldown -1
    self.shoot_cooldown = self.shoot_cooldown -1
end

function imp:mode_controller()
    if self.mode=="stop" then return end
    
    if self.mode_cooldown <= 0 then
        -- seleccionar mode d'acció
        local last_mode=self.mode
        self.mode_cooldown = 150+math.random(50)-1
        self.mode=math.random(#self.fight_modes)
    
        if self.mode==self.fight_modes["super"] and self.super_cooldown>0 then self.mode=self.fight_modes["shot"] end
        if self.mode==self.fight_modes["shot"]  and self.shot_cooldown>0  then self.mode=self.fight_modes["chase"] end
        
        print("cambiar modo => "..self.fight_modes[self.mode])
    end
    --     -- if self.mode==last_mode then self.mode=((last_mode+1)%#self.fight_modes)+1 end
    -- elseif self.mode_cooldown == 0 then
    --     if self.shot_cooldown<=0 then self.mode=self.fight_modes["shot"] end;
    -- end
    
    self:do_flip(abad)
    -- self:movement(abad)
    
    -- comprovar colisio en l'abad
    if viewp:inside(self.x, self.y, self.w, self.h) then
        if collision(abad,self) then
            abad_hurt(1)
        end
    end
    
    --if imp.wait==6 then
    --    imp.wait=0
    --     if not imp.enabled then
    --         imp.counter=imp.counter-1
    --         local r = math.random(0,imp.counter-1)
    --         --print(r)
    --         if imp.counter==1 or r==1 then
    --             imp.init()
    --         end
    --         return
    --     end
    -- 
    --    imp.step=(imp.step+1)%4
    --    imp.frame=imp.anim[imp.step+1]
    -- 
    --     if imp.flip then
    --         imp.x=imp.x-2
    --         if imp.x==78 then
    --             fireball.init(imp.hab,imp.x+8,imp.y+4,imp.flip)
    --             sound.play(audio_hit)
    --             imp.flip=not imp.flip
    --         elseif imp.x==-12 then
    --             imp.reset()
    --         end
    --     else
    --         imp.x=imp.x+2
    --         if imp.x==4 then
    --             fireball.init(imp.hab,imp.x+8,imp.y+4,imp.flip)
    --             sound.play(audio_hit)
    --             imp.flip=not imp.flip
    --         elseif imp.x==92 then
    --             imp.reset()
    --         end
    --     end
    -- 
    --end
end

