open_pairs_of_images_scene00 = {}

local self = open_pairs_of_images_scene00

self.params = {
   box_pos =
   {
      { X = 83,  Y = 102 },
      { X = 208, Y = 49  },
      { X = 50,  Y = 284 },
      { X = 69,  Y = 477 },
      { X = 156, Y = 353 },
      { X = 228, Y = 500 },
      { X = 379, Y = 452 },
      { X = 284, Y = 321 },
      { X = 308, Y = 155 },
      { X = 422, Y = 81  },
      { X = 407, Y = 269 },
      { X = 187, Y = 208 }
   },
   disk_pos =
   {
      { X = 603, Y = 63  },
      { X = 569, Y = 189 },
      { X = 714, Y = 150 },
      { X = 655, Y = 290 },
      { X = 541, Y = 530 },
      { X = 680, Y = 500 },
      { X = 860, Y = 492 },
      { X = 750, Y = 406 },
      { X = 898, Y = 363 },
      { X = 793, Y = 269 },
      { X = 885, Y = 164 },
      { X = 551, Y = 384 }
   },
   image =
   {
      box_postfix  = "_02",
      disk_postfix = "_01",
      prefix       = "scenes_scene00_01_minigame_minigame01_disk",
      box_white    = "scenes_scene00_01_minigame_minigame01_disk00_02_white",
      disk_white   = "scenes_scene00_01_minigame_minigame01_disk00_01_white"
   },
   time_show       = 700,  -- Время порявления (изчезновения) изображения
   time_wait       = 1200,  -- Время задержки при неправильном вводе
   time_shine_wait = 700,  -- Время задержки перед сиянием при правильном вводе (от момента вравильного клика), то есть сюда включено время time_show
   time_shine      = 300,   -- Время задержки при неправильном вводе
   time_win        = 1000,
   
   one_sound  = "mini_game_mini_game_open_pairs_select_01",
   fail_sound = "mini_game_mini_game_open_pairs_select_false_01",
   pair_sound = "mini_game_mini_game_open_pairs_select_true_01"
}
-- state
-- 0 закрыт
-- 1 открыт
-- 2 открыт с парой
-- 3 открыт с неправильной парой и стремиться к 0

function self.Init (_owner)
   sminigames.SetStandartScriptName(_owner, open_pairs_of_images_scene00)

   self.owner   = _owner
   self.timer   = __create_timer ()
   self.effects = {}
   self.shine   = {}
   
   self.Reset ()
end

function self.GetRandomArray (_size)
   local array = {}
   for i=1, _size do
      array[i] = i
   end
   
   for i=1, _size do
      local n = math.random (_size)
      local m = math.random (_size)
      local t = array[n]
      array[n] = array[m]
      array[m] = t
   end
   return array
end

function self.GetIndex (_i)
   if _i < 10 then
      return '0'..tostring (_i)
   end
   return tostring (_i)
end

function self.CreateImage (_item, _pos)
   self.owner.AddWidget (_item)
   _item.SetOffset (_pos.X, _pos.Y)
--   _item.SetOffset (_pos.X - _item.GetSize ().X / 2, _pos.Y - _item.GetSize ().Y / 2)
end

function self.CreateItem (_type, _i, _index_array)
   local index     = self.GetIndex (_i)
   local result  =
   {
      image = sf.gui.CImageWidget (self.params.image.prefix..index..self.params.image[_type.."_postfix"], "", 0, 0),
      up    = sf.gui.CImageWidget (self.params.image.prefix.."00" ..self.params.image[_type.."_postfix"], "", 0, 0),
      white = sf.gui.CImageWidget (self.params.image[_type.."_white"], "", 0, 0),
      state = 0
   }
   self.CreateImage (result.image, self.params[_type.."_pos"][_index_array [_i] ])
   self.CreateImage (result.up,    self.params[_type.."_pos"][_index_array [_i] ])
   self.CreateImage (result.white, self.params[_type.."_pos"][_index_array [_i] ])
   self.SetAlpha (result.white, 0)
   return result
end

function self.Reset ()
   assert (#self.params.box_pos == #self.params.disk_pos)
   local size  = #self.params.box_pos
   local boxs  = self.GetRandomArray (size)
   local disks = self.GetRandomArray (size)

   self.items = {}
   for i = 1, size do
      self.items[i] =
      {
         disk  = self.CreateItem ("disk", i, disks),
         box   = self.CreateItem ("box" , i, boxs)
      }
      self.shine[i] = 0
   end
   self.effects = {}
end

function self.IsIn (_widget, _pos)
   local is_enabled = (sf.misc.BitwiseAnd(_widget.GetFlags(), sf.gui.CBaseWidget.FlagDisabled) == 0)
   if is_enabled == 0 then
      return false
   end 
   return _widget.GetPoly().IsContains(_pos.X, _pos.Y)
end

function self.GetAnother (_type)
   if "disk" == _type then
      return "box"
   end
   return "disk";
end

function self.OnItemMouseDown (_i, _pos, _type)
   local is = false
   local item = self.items[_i]
   if item[_type].state == 0 and self.IsIn (item[_type].image, _pos)then
      item[_type].state = 1
      is = true
      self.CreateEffect ("ChangeAlpha",  self.params.time_show, { widget = item[_type].up, type  = "dec"})
      is = true
      local size = #self.items
      -- Проверка на необходимость спрятать другие изображения
      for j = 1, size do
         if _i ~= j then
            if self.items[j][_type].state == 1 then
               self.items[j][_type].state = 0
               self.CreateEffect ("ChangeAlpha",  self.params.time_show, { widget = self.items[j][_type].up, type  = "inc"})
            end
         end
      end
   end
   return is
end

function self.OnMouseDown(_owner, _pos, _button, _keyboard_state, _broadcast)
   local size  = #self.items
   local is = false
   local pair = false
   local two = false
   for i = 1, size do
      local item = self.items[i]
      is = is or self.OnItemMouseDown (i, _pos, "box")
      is = is or self.OnItemMouseDown (i, _pos, "disk")
      
      -- Проверка на открытие двух одинаковых
      if self.items[i].box.state == 1 and self.items[i].disk.state == 1 then
         pair = true
         self.items[i].box.state  = 2
         self.items[i].disk.state = 2
         self.CreateEffect ("Wait",  self.params.time_shine_wait                         , { type = "ChangeAlpha", time = self.params.time_shine, params = { widget = self.items[i].box .white, type = "inc" } } )
         self.CreateEffect ("Wait",  self.params.time_shine_wait + self.params.time_shine, { type = "ChangeAlpha", time = self.params.time_shine, params = { widget = self.items[i].box .white, type = "dec" } } )
         self.CreateEffect ("Wait",  self.params.time_shine_wait                         , { type = "ChangeAlpha", time = self.params.time_shine, params = { widget = self.items[i].disk.white, type = "inc" } } )
         self.CreateEffect ("Wait",  self.params.time_shine_wait + self.params.time_shine, { type = "ChangeAlpha", time = self.params.time_shine, params = { widget = self.items[i].disk.white, type = "dec" } } )
         self.CheckWin ()
      end

   end
   -- Проверка на открытие двух разных
   local b = 0
   local d = 0
   for i = 1, size do
      if self.items[i].box.state  == 1 then
         b = i
      end
      if self.items[i].disk.state == 1 then
         d = i
      end
   end
   if b ~= 0 and d ~= 0 then
      two = true
      self.items[b].box.state  = 3
      self.items[d].disk.state = 3
      self.CreateEffect ("Error", self.params.time_show + self.params.time_wait, { box = b, disk = d})
   end
   if pair then
     sf.core.g_Application.GetAudioManager().Play(self.params.pair_sound, -2, -2, -2, -2, -2)
   end
   if pair == false and two then
      sf.core.g_Application.GetAudioManager().Play(self.params.fail_sound, -2, -2, -2, -2, -2)
   end
   if pair == false and two == false and is then
      sf.core.g_Application.GetAudioManager().Play(self.params.one_sound, -2, -2, -2, -2, -2)
   end
   if is == true then
      return true
   end
   return false
end

function self.OnUpdate (_owner)
   self.UpdateEffect (_owner)
   return true
end

function self.SetAlpha (_widget, _alpha)
   local color = sf.graphics.Color (_widget.GetColor());
   color.Alpha = _alpha;
   _widget.SetColor(color);
end

function self.CreateEffect (_type, _live_time, _params)
   local effects = self.effects
   local i = #effects + 1;
   effects[i] = 
   {
      params = _params,
      type =   _type,
      live_time = _live_time
   };
   effects[i].start_time = self.timer.Get().GetTime();
end

function self.UpdateEffect (_owner)
   local cur_time = self.timer.Get().GetTime()
   local remove = nil
   local effects = self.effects
   for i = 1, #effects do
      local effect = effects[i]
      local time = cur_time -  effect.start_time;
      local dead = false
      if effect.live_time ~= 0 and time >= effect.live_time then
         time = effect.live_time
         if remove == nil then
            remove = {}
            remove[1] = i
         else
            remove[#remove + 1] = i
         end
         dead = true
      end
      local k = 1.0;
      if effect.live_time ~= 0 then
         k = time / effect.live_time;
      end 
      if effect.type == "Wait" then
         if dead then
           self.CreateEffect (effect.params.type, effect.params.time, effect.params.params)
         end
      end
      if effect.type == "RemoveWidget" then
         if dead then
            effect.params.owner.RemoveWidget (effect.params.widget)
         end
      end
      if effect.type == "ChangeAlpha" then
         local alpha = nil
         if effect.params.type == "inc" then
            alpha = 255.0 * k
         else
            alpha = 255.0 * (1.0 - k)
         end
         self.SetAlpha (effect.params.widget, alpha)
      end
      if effect.type == "Error" then
         if dead then
            self.items[effect.params.box ].box .state = 0
            self.items[effect.params.disk].disk.state = 0
            self.CreateEffect ("ChangeAlpha", self.params.time_show, { widget = self.items[effect.params.box ].box. up, type = "inc" } )
            self.CreateEffect ("ChangeAlpha", self.params.time_show, { widget = self.items[effect.params.disk].disk.up, type = "inc" } )
         end
      end
      if effect.type == "Win" then
         if dead then
            _owner.SetGameResult(1)
            _owner.OnEndGame()
         end
      end
   end
   if remove ~= nil then
      for i = 1, #remove do
         local j = #remove - i + 1
         table.remove (effects, remove[j])
      end
   end
end

function self.CheckWin ()
   if self.win ~= true then
      local is = true
      for i = 1, #self.items do
         if self.items[i].box.state ~= 2 and self.items[i].disk.state ~= 2 then
            is = false
            break
         end
      end
      if is == true then
         self.win = true
         self.CreateEffect ("Win", self.params.time_win)
      end
   end
end
