class 'GameCogwheels' (Script)

function GameCogwheels:__init() super()
    self.selectedCogwheel   = nil
    self.needRotate         = false
    
    self.cogwheels          = {}    
    self.activeCogwheels    = {}
    self.inplaceCogwheels   = {}
    
    self.center = Position(633, 340)
    
    self.firstCogwheel      = nill
    
    self.radius = 11
    
    self.mouseEnabled = true
    self.cureentBad=nil
    self.points = {Position(648, 502), Position(739, 487), Position(562,470), Position(495,405), Position(511,324), Position(627,322), Position(490,217), Position(583,203)}
end

function GameCogwheels:on_attach()
    local scene     = self:scene()
    local object
    self.soundRotate = self:scene():sound('cowhils_rotate_sound')
    self.soundPut_true=self:scene():sound('cowhils_put_true')
    self.soundPut_false=self:scene():sound('cowhils_put_false')
    for i=1,8 do
        object = scene:object('c'..i)
    
        table.insert(self.cogwheels, {  obj                 = object,
                                        speed               = 0,
                                        center              = 0,
                                        angle               = 0,
                                        radius              = 0, 
                                        direction           = 1, 
                                        originalPosition    = object:position(),
                                        index               = i,
                                        links               = {}})
                                        
        self:initCogwheel(self.cogwheels[i])
    end
    
    
    self.needRotate = false
end

function GameCogwheels:initCogwheel(holder)
    local cogwheel  = holder.obj
    local speed
    local width     = cogwheel:dimensions():lx()
    local height    = cogwheel:dimensions():ly()
    
    holder.center = Position(width/2, height/2)
    holder.radius = width/2
    
    holder.speed = 90
end

function GameCogwheels:on_update(dt)
    if self.needRotate then
        local holder
        for i=1,#self.activeCogwheels do
            holder = self.cogwheels[self.activeCogwheels[i]]
            
            holder.obj:set_angle(holder.angle, holder.center)
            
            holder.angle = holder.angle + holder.direction * holder.speed * dt
            
            if holder.angle > 360 then
                holder.angle = 360 - holder.angle
            elseif holder.angle < -360 then
                holder.angle = 360 + holder.angle
            end
        end
    end
end

function GameCogwheels:on_lb_down()
    if not self.mouseEnabled then
        return
    end

    local scene = self:scene()
    local selection = scene:overed_object()

    if self.selectedCogwheel then
        self:release_capture(self.selectedCogwheel.obj)
        self:checkDropPosition()

        self.selectedCogwheel = nil
    else
      if selection then
          for i=1,#self.cogwheels do
              local obj = self.cogwheels[i].obj
              if selection:name() == obj:name() then
                  self:capture_object(obj)

                  self.selectedCogwheel = self.cogwheels[i]

                  self:removeFrom(self.selectedCogwheel.obj:name(), self.cogwheels, self.activeCogwheels)

                  if self.firstCogwheel and (self.firstCogwheel.obj:name() == self.selectedCogwheel.obj:name()) then
                        self.soundRotate:stop()
                      self.firstCogwheel = nil
                  end

                  self:removeFrom(self.selectedCogwheel.obj:name(), self.cogwheels, self.inplaceCogwheels)
                  self:unlinkAll(self.selectedCogwheel)
                  self:updateLinks()
                  break
              end
          end
      end
    end
end

function GameCogwheels:checkDropPosition()
    if self:intersect_bad() then
    else
        self.selectedCogwheel.obj:set_position(self.selectedCogwheel.originalPosition)
        return
    end

    local point
    local objPosition   = Position( self.selectedCogwheel.obj:position():x()+self.selectedCogwheel.center:x(), 
                                    self.selectedCogwheel.obj:position():y()+self.selectedCogwheel.center:y())
    
    local match = false
    local dist
    local pointIndex = nil
    
    for i=1,#self.points do
        point   = self.points[i]
        dist    = math.sqrt(    math.pow(point:x()-objPosition:x(),2)+
                                math.pow(point:y()-objPosition:y(),2))

        if dist < self.radius then -- found center
           --print('1')
                                                                   --music
            self.selectedCogwheel.obj:set_position( Position(   point:x()-self.selectedCogwheel.center:x(), 
                                                                point:y()-self.selectedCogwheel.center:y()))
                                                                
            pointIndex = i
-- look around            
            match = self:checkLinks()
            break

        end
    end

    if match then -- cogwheel in mechanism
        table.insert(self.inplaceCogwheels, self.selectedCogwheel.index)
          self.soundPut_true:play(false)
      --  print('2')
        if pointIndex == 1 then
          --  print('3')
            self.firstCogwheel = self.selectedCogwheel
            self.soundRotate:play(true)                                        --music
        end
        self.cureentBad=true
    else -- have conflicts or just removed
-- move to original
       -- print('4')
        self.cureentBad=false
        self.selectedCogwheel.obj:set_position(self.selectedCogwheel.originalPosition)
        
        self:removeFrom(self.selectedCogwheel.obj:name(), self.cogwheels, self.inplaceCogwheels)
       --       print(self.firstCogwheel)
       --               print( self.firstCogwheel.obj:name())
      --  print(self.selectedCogwheel.obj:name())
        if self.firstCogwheel and (self.firstCogwheel.obj:name() == self.selectedCogwheel.obj:name()) then
            self.firstCogwheel = nil

            self.soundRotate:stop()                                            --music
        end
        self.selectedCogwheel=nil
    end
    self:updateLinks()

end

function GameCogwheels:checkLinks()
    local intersect = self:intersect()
    for i=1,#self.inplaceCogwheels do
        holder  = self.cogwheels[self.inplaceCogwheels[i]].radius
    end

    if #intersect then
        local dist
        local radius = self.selectedCogwheel.radius
        local radius2
        
        for i=1,#intersect do
            dist    = intersect[i][2]
            radius2 = intersect[i][1].radius
            
            if dist < radius+radius2-10 then
                return false
            else
                self:link(self.selectedCogwheel, intersect[i][1])
            end
        end
    end
    
    return true
end

-- TODO: need optimization
function GameCogwheels:updateLinks()
    self.activeCogwheels = {}
    
    if self.firstCogwheel == nil then
        return
    end
--    if not self.cureentBad then
--     return
--    end

    self.firstCogwheel.direction = 1
    self:activate(self.firstCogwheel, nil)

    if #self.activeCogwheels then
        self.needRotate = true
        
        self:checkComplete()
    else        
        self.needRotate = false
    end
end

-- TODO: need optimization
function GameCogwheels:activate(holder, parentHolder)
    local linkedHolder
    
    table.insert(self.activeCogwheels, holder.index)
    
    for i=1,#holder.links do
        linkedHolder = holder.links[i]
        
        if not (parentHolder and (parentHolder.obj:name() == linkedHolder.obj:name())) then
            linkedHolder.direction = holder.direction*-1        
            self:activate(linkedHolder, holder)
        end        
    end    
end

function GameCogwheels:link(holder1, holder2)
    local name1 = holder1.obj:name()
    local name2 = holder2.obj:name()

    local holder
    local found = false
    
    for i=1,#holder1.links do
        holder = holder1.links[i]
        
        if holder.obj:name() == name2 then
            found = true
            break
        end
    end
    
    if not found then
        table.insert(holder1.links, holder2)
    end
    
    found = false
    
    for i=1,#holder2.links do
        holder = holder2.links[i]
        
        if holder.obj:name() == name1 then
            found = true
            break
        end
    end

    if not found then
        table.insert(holder2.links, holder1)
    end
end

function GameCogwheels:unlink(holder1, holder2)
    self:removeFrom(holder2.obj:name(), holder1.links)
    self:removeFrom(holder1.obj:name(), holder2.links)
end

function GameCogwheels:unlinkAll(holder)
    local name = holder.obj:name()

    local linkedHolder
    local found = false
    
    for i=1,#holder.links do
        linkedHolder = holder.links[i]
        
        self:removeFrom(name, linkedHolder.links)
    end
    
    holder.links = {}
end

function GameCogwheels:removeFrom(objName, objTable, indexTable)
    local holder
    
    if indexTable then
        for i=1,#indexTable do
            holder = objTable[indexTable[i]]
            
            if holder.obj:name() == objName then
                table.remove(indexTable, i)
                break
            end
        end
    else
        for i=1,#objTable do
            holder = objTable[i]
            
            if holder.obj:name() == objName then
                table.remove(objTable, i)
                break
            end
        end
    end
end

function GameCogwheels:intersect()
    local result = {}
    local dist
    local tmp = Position(   self.selectedCogwheel.obj:position():x()+self.selectedCogwheel.center:x(), 
                            self.selectedCogwheel.obj:position():y()+self.selectedCogwheel.center:y())

    local holder
    for i=1,#self.inplaceCogwheels do
        holder  = self.cogwheels[self.inplaceCogwheels[i]]
        dist    = math.sqrt(    math.pow((holder.obj:position():x()+holder.center:x()-tmp:x()),2)+
                                math.pow((holder.obj:position():y()+holder.center:y()-tmp:y()),2))
        
        if dist <= (holder.radius+self.selectedCogwheel.radius) then
            table.insert(result, {holder,dist})
        end
    end 

    return result
end

function GameCogwheels:intersect_bad()
    local result = {}
    local dist
    local tmp = Position(   self.selectedCogwheel.obj:position():x()+self.selectedCogwheel.center:x(),
        self.selectedCogwheel.obj:position():y()+self.selectedCogwheel.center:y())

    local holder
    for i=1,#self.inplaceCogwheels do
        holder  = self.cogwheels[self.inplaceCogwheels[i]]
        dist    = math.sqrt(    math.pow((holder.obj:position():x()+holder.center:x()-tmp:x()),2)+
                math.pow((holder.obj:position():y()+holder.center:y()-tmp:y()),2))

        if dist <= (holder.radius+self.selectedCogwheel.radius)-10 then
           -- table.insert(result, {holder,dist})
       -- else
         return false
        end

    end

    return true
end


function GameCogwheels:checkComplete()
    if #self.activeCogwheels == 8 then
        self.mouseEnabled = false
       self:scene():execute_action('complete_gamecogwheels')       
    end
end