enter_password_on_mouse_level08_composer = {}
local self = enter_password_on_mouse_level08_composer

self.params = 
{
   password = {1, 5, 1, 4, 1, 7, 6, 5, 4, 3, 2, 1},

   -- Описаний нот
   notes =
   {
      {
         id = "note01",  -- Идентификатор клипа с нотой
         sound_on_click ="note_c_01", -- Звук при нажатии
         dance_offset = sf.misc.FloatVector(5.0, 200.0), -- Место, возле диктофона
         out_of_screen_offset = sf.misc.FloatVector(1124.0, -100.0) -- Место, куда нлта улетит при неправильном нажатии
      },
      {
         id = "note02",
         sound_on_click ="note_g",
         dance_offset = sf.misc.FloatVector(30.0, 208.0),
         out_of_screen_offset = sf.misc.FloatVector(-100.0, -100.0)
      },
      {
         id = "note03",
         sound_on_click ="note_c_01",
         dance_offset = sf.misc.FloatVector(55.0, 200.0),
         out_of_screen_offset = sf.misc.FloatVector(308.0, 868.0)
      },
      {
         id = "note04",
         sound_on_click ="note_f",
         dance_offset = sf.misc.FloatVector(80.0, 206.0),
         out_of_screen_offset = sf.misc.FloatVector(1124.0, 389.0)
      },
      {
         id = "note05",  -- Идентификатор клипа с нотой
         sound_on_click ="note_c_01", -- Звук при нажатии
         dance_offset = sf.misc.FloatVector(105.0, 200.0), -- Место, возле диктофона
         out_of_screen_offset = sf.misc.FloatVector(1124.0, -100.0) -- Место, куда нлта улетит при неправильном нажатии
      },
      {
         id = "note06",
         sound_on_click = "note_b",
         dance_offset = sf.misc.FloatVector(130.0, 212.0),
         out_of_screen_offset = sf.misc.FloatVector(308.0, -100.0)
      },
      {
         id = "note07",
         sound_on_click ="note_a",
         dance_offset = sf.misc.FloatVector(155.0, 210.0),
         out_of_screen_offset = sf.misc.FloatVector(-100.0, 868.0)
      },
      {
         id = "note08",
         sound_on_click ="note_g",
         dance_offset = sf.misc.FloatVector(180.0, 208.0),
         out_of_screen_offset = sf.misc.FloatVector(1124.0, 868.0)
      },
      {
         id = "note09",
         sound_on_click ="note_f",
         dance_offset = sf.misc.FloatVector(205.0, 206.0),
         out_of_screen_offset = sf.misc.FloatVector(716.0, -100.0)
      },
      {
         id = "note10",
         sound_on_click ="note_e",
         dance_offset = sf.misc.FloatVector(230.0, 204.0),
         out_of_screen_offset = sf.misc.FloatVector(-100.0, 389.0)
      },
      {
         id = "note11",
         sound_on_click ="note_d",
         dance_offset = sf.misc.FloatVector(255.0, 202.0),
         out_of_screen_offset = sf.misc.FloatVector(716.0, 868.0)
      },
      {
         id = "note12",
         sound_on_click ="note_c_01",
         dance_offset = sf.misc.FloatVector(280.0, 200.0),
         out_of_screen_offset = sf.misc.FloatVector(1124.0, -100.0)
      }
   },

   time_to_show = 2550, -- Время, за которое нота проявляется с альфой
   time_to_dance_move = 3000, -- Время, за которое нота долетает до диктофона
   time_to_out_of_screen_move = 3000, -- Время, за которое нота улетает за край экрана / время блокировки кнопок / время до перезапуска
   
   float_speed = 2.2, -- Скорость вращения нот
   float_size = 3.0,  -- Амплитуда вращения нот
   
   -- Клавиши, которые будут заблокированы при не правильном нажатии 
   disabled_buttons =
   {
      "5", "7", "9"
   },

   sound_on_break = "mini_game_mini_game_composer_false_01", -- Звук, который будет проигран при не правильном нажатии
   
   sound_on_click = "",
   sleep = 600.0 -- пауза перед сбросом в случае неправильного ввода / пауза перед закрытием в случае правильного ввода
}

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 i = #self.effects + 1;
   self.effects[i] = 
   {
      params = _params,
      type =   _type,
      live =   true,
      live_time = _live_time
   };
   self.effects[i].start_time = self.timer.Get().GetTime();
   if self.effects[i].type == "Move" then
      self.effects[i].offset = sf.misc.FloatVector (0.0, 0.0);
      for j=1,i-1 do
         if self.effects[j].type == "Move" and self.effects[j].params.widget == _params.widget then
            self.effects[j].live = false;
         end
      end
   end
   if self.effects[i].type == "Float" then
      self.effects[i].offset = sf.misc.FloatVector (0.0, 0.0);
   end
end

function self.Reset(_owner)
   self.current_sequence = {}      
   self.effects = {}
   for i=1, #self.params.notes do
      self.SetAlpha(self.params.notes[i].widget, 0);
      self.params.notes[i].widget.SetOffset (self.params.notes[i].start_offset.X, self.params.notes[i].start_offset.Y);
      local params = 
      { 
         widget = self.params.notes[i].widget
      };
      self.CreateEffect ("Float", 0, params);
   end
   self.DisableKey (_owner, false);
   self.active = true;
end

function self.UpdateOffset(effect_id, offset)
   local result = sf.misc.FloatVector (self.effects[effect_id].params.widget.GetOffset()) + offset - self.effects[effect_id].offset;
   self.effects[effect_id].offset = offset;
   self.effects[effect_id].params.widget.SetOffset (result.X, result.Y);
end

function self.OnUpdate(_owner)
   for i=1,#self.effects do
      if self.effects[i].live == true then
         local time = self.timer.Get().GetTime() -  self.effects[i].start_time;
         if self.effects[i].live_time ~= 0 and time >= self.effects[i].live_time then
            time = self.effects[i].live_time;
            self.effects[i].live = false;
         end
         local k = 1.0;
         if self.effects[i].live_time ~= 0 then
            k = time / self.effects[i].live_time;
         end 
         if self.effects[i].type == "Show" then
            local alpha = 255.0 * k; 
            self.SetAlpha (self.effects[i].params.widget, alpha);
         end
         if self.effects[i].type == "Move" then
            self.UpdateOffset(i, self.effects[i].params.distance * k);
         end
         if self.effects[i].type == "Float" then
            self.UpdateOffset(i, sf.misc.FloatVector (math.cos (time * self.params.float_speed * 3.1415 / 1000.0), math.sin (time * self.params.float_speed * 3.1415 / 1000.0)) * self.params.float_size);
         end
         if self.effects[i].type == "Hide" and k == 1 then
            self.Reset (_owner);
         end
      end
   end
end

function self.DisableKey (_owner, _disable)
   for k = 1, #self.params.disabled_buttons do
      local widget = __cast(_owner.GetWidget(self.params.disabled_buttons[k]), sf.gui.CButtonWidget); 
      widget.DisableButton(_disable);
   end
end

function self.OnChildAction(_owner, _action, _child)
   if _action.c_str() == "pressed" and self.active == true then               
      local number = tonumber(_child.GetId().c_str())
      if number then
         table.insert(self.current_sequence, number)
                       
         local current_length = #self.current_sequence
         local target_length = #self.params.password
                        
         assert(current_length <= target_length)
                        
         local correctly = true
         for i=1, current_length do
            if self.current_sequence[i] ~= self.params.password[i] then
               correctly = false
               break
            end
         end
         local i = #self.current_sequence;
         local id = tostring(self.current_sequence[#self.current_sequence])
         if correctly == false then
            self.active = false;
            for k = 1, current_length-1 do
               local params = 
               {
                  widget = self.params.notes[k].widget,
                  distance = self.params.notes[k].out_of_screen_offset - self.params.notes[k].widget.GetOffset()
               };
               self.CreateEffect ("Move", self.params.time_to_out_of_screen_move, params);
            end
            self.CreateEffect ("Hide", self.params.time_to_out_of_screen_move);
            sf.core.g_Application.GetAudioManager().Play(_T(self.params.sound_on_break), -2, -2, -2, -2, -2);
            self.DisableKey(_owner, true);
         else
            -- Отлетает нотка
            sf.core.g_Application.GetAudioManager().Play(_T(self.params.notes[i].sound_on_click), -2, -2, -2, -2, -2);
            local params = 
            { 
               widget = self.params.notes[i].widget
            };
            self.CreateEffect ("Show", self.params.time_to_show, params);
            params = 
            {
               widget = self.params.notes[i].widget,
               distance = self.params.notes[i].dance_offset - self.params.notes[i].widget.GetOffset ()
            };
            self.CreateEffect ("Move", self.params.time_to_dance_move, params);

            if current_length == target_length then
                _owner.SetGameResult(1)
                _owner.OnEndGame()
            end 
         end
      end
   end
end

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

   assert(#self.params.notes == #self.params.password)
   for i=1, #self.params.notes do
      self.params.notes[i].widget = __cast(_owner.GetWidget("note"..i, true), sf.gui.CClipWidget);
      self.params.notes[i].start_offset = sf.misc.FloatVector (self.params.notes[i].widget.GetOffset());
   end

   self.timer = __create_timer();
   self.active = true;

   self.Reset(_owner);
end
