function BejeweledMinigame::start(%this)
{
   %this.lastCursorX = 0;
   %this.lastCursorY = 0;
   
   sfxPlay(MusicGangsterLevel);
}

function BejeweledMinigame::onWake(%this)
{
   %this.gameMode = "Twist";   
   
   %this.selectedJew = "";
   %this.matchStackCount = 0;
   %this.gemsToCheck = "";
   
   %this.gemTypeCount = 4;
   %this.minGemsPerMatch = 4;
   %this.gemsToMatchOnSwapAtStart = 4;
   
   exec("~/data/ui/minigame/bejeweled/"@playMinigameDlg.currentLevel@"/BejeweledConfig.cs");
   
   // Set skip button
   if(($CurTake $= 2 && playMinigameDlg.currentLevel $= "GangsterLevel") ||
      ($CurTake $= 1 && playMinigameDlg.currentLevel $= "SciFiLevel"))
      BejeweledSkipButton.setBitmap("scriptsAndAssets/data/ui/minigame/quit.png");
   else   
      BejeweledSkipButton.setBitmap("scriptsAndAssets/data/ui/minigame/skip.png");   

   %this.createLevel();
   
   BejeweledGui.init();

   // Force resizing
   %this.setExtent(getWord(Canvas.extent,0), getWord(Canvas.extent,1));
   Canvas.setWidescreen(MinigameRefCenter, 0, false);
}

function BejeweledMinigame::onResize(%this, %width, %height)
{
   Canvas.setWidescreen(MinigameRefCenter, 2000, true);
   
   if (!BejeweledGui.ConfettiIsPlaying)
   {
      onLoseFocus();
      onGainFocus();
      onResumeAfterLosingFocus();
   }   
}

function BejeweledMinigame::createLevel(%this) 
{  
   if (%this.gameMode $= "Twist") //Make the game less easy at start
      %this.minGemsPerMatch -= 1;
   
   %this.cleanMatrixRect(0, 0, BejeweledMinigame.numRows, BejeweledMinigame.numCols);

   for (%i = 0; %i < BejeweledMinigame.numRows; %i++)
      for (%j = 0; %j < BejeweledMinigame.numCols; %j++)
         %this.setRndGem(%i, %j, false);

   %this.insertGemsToMatch(%this.gemsToMatchOnSwapAtStart);

   if (%this.gameMode $= "Twist") //restore to check matches correctly
      %this.minGemsPerMatch += 1;
}

function BejeweledMinigame::cleanMatrixRect(%this, %i0, %j0, %rowCount, %colCount)
{
   %k = 30;
   for (%i = %i0; %i < %i0 + %rowCount; %i++)
      for (%j = %j0; %j < %j0 + %colCount; %j++)
         %this.gemMatrix[%i, %j] = %k++;
}

function BejeweledMinigame::setRndGem(%this, %i, %j, %matchOnSwap)
{
  %gem = getRandom(%this.gemTypeCount-1);
   for (%attempt = 0; %attempt < %this.gemTypeCount; %attempt++)
   {
      %this.setGem(%gem+%attempt > %this.gemTypeCount-1? %gem+%attempt - %this.gemTypeCount : %gem+%attempt, %i, %j);
      if (!%this.match(%i, %j) && (%matchOnSwap == %this.matchOnSwap(%i, %j)))
         return true;
   }
   
   return false;
}

function BejeweledMinigame::getGem(%this, %i, %j)
{
   if ((%i < 0)||(%i >= BejeweledMinigame.numRows)||(%j < 0)||(%j >= BejeweledMinigame.numCols))
      return -1;
   
   return %this.gemMatrix[%i, %j];
}

function BejeweledMinigame::setGem(%this, %gem, %i, %j)
{
   if ((%i < 0)||(%i >= BejeweledMinigame.numRows)||(%j < 0)||(%j >= BejeweledMinigame.numCols))
      return;
   
   %this.gemMatrix[%i, %j] = %gem;
   
   BejeweledGui.updateGemBitmap(%gem, %i, %j);
}

function BejeweledMinigame::swap(%this, %i1, %j1, %i2, %j2 )
{
   %gem1 = %this.getGem(%i1, %j1);
   if (%gem1 < 0)
      return false;
   
   %gem2 = %this.getGem(%i2, %j2);
   if (%gem2 < 0)
      return false;
      
   if (!(mAbs(%i1 - %i2) == 1 && mAbs(%j1 - %j2) == 0) && !(mAbs(%i1 - %i2) == 0 && mAbs(%j1 - %j2) == 1))
      return false;
      
   
   %this.setGem(%gem2, %i1, %j1);
   %this.setGem(%gem1, %i2, %j2);
   
   return true;
}

function BejeweledMinigame::matchOnSwap(%this, %i, %j)
{
   if (%this.matchOnSpecificSwap(%i+1,%j,%i,%j,%i+1,%j))
      return true;  
   if (%this.matchOnSpecificSwap(%i-1,%j,%i,%j,%i-1,%j))
      return true;  
   if (%this.matchOnSpecificSwap(%i,%j+1,%i,%j,%i,%j+1))
      return true;  
   if (%this.matchOnSpecificSwap(%i,%j-1,%i,%j,%i,%j-1))
      return true;  


   for (%k = %i - 2; %k <= %i + 2; %k++)
   {
      if (%this.matchOnSpecificSwap(%i,%j,%k,%j,%k,%j+1))
         return true;  
      if (%this.matchOnSpecificSwap(%i,%j,%k,%j,%k,%j-1))
         return true;  
   }

   for (%k = %j - 2; %k <= %j + 2; %k++)
   {
      if (%this.matchOnSpecificSwap(%i,%j,%i,%k,%i+1,%k))
         return true;  
      if (%this.matchOnSpecificSwap(%i,%j,%i,%k,%i-1,%k))
         return true;  
   }
   
   if (%this.matchOnSpecificSwap(%i,%j,%i-2,%j,%i-3,%j))
      return true;  
   if (%this.matchOnSpecificSwap(%i,%j,%i+2,%j,%i+3,%j))
      return true;  
   if (%this.matchOnSpecificSwap(%i,%j,%i,%j-2,%i,%j-3))
      return true;  
   if (%this.matchOnSpecificSwap(%i,%j,%i,%j+2,%i,%j+3))
      return true;  

   return false;
}

function BejeweledMinigame::matchOnSpecificSwap(%this, %iM, %jM, %i1, %j1, %i2, %j2)
{
   if (%this.swap(%i1,%j1,%i2,%j2))
   {
      %match = %this.match(%iM, %jM);

      %this.swap(%i1,%j1,%i2,%j2);

      if (%match)
         return true;
   }
   
   return false;
}

function BejeweledMinigame::twist(%this, %i, %j)
{
   %gem1 = %this.getGem(%i, %j);
   if (%gem1 < 0)
      return false;
   
   %gem2 = %this.getGem(%i, %j + 1);
   if (%gem2 < 0)
      return false;

   %gem3 = %this.getGem(%i + 1, %j + 1);
   if (%gem3 < 0)
      return false;

   %gem4 = %this.getGem(%i + 1, %j);
   if (%gem4 < 0)
      return false;

   %this.setGem(%gem1, %i, %j + 1);
   %this.setGem(%gem2, %i + 1, %j + 1);
   %this.setGem(%gem3, %i + 1, %j);
   %this.setGem(%gem4, %i, %j);
   
   return true;
}

function BejeweledMinigame::match(%this, %i, %j)
{
   if (%this.getMatch(%i, %j) !$= "")
      return true;
      
   return false;
}

function BejeweledMinigame::getMatch(%this, %i, %j)
{
   %n = 0;
   %l = 0;
   %m = %this.minGemsPerMatch - 1;
   
   %size = BejeweledMinigame.numRows - 1;
   
   %matchPos = "";
   for (%k = 0; %k < %size; %k++)
   {
      if (%this.getGem(%k, %j) == %this.getGem(%k + 1, %j))
      {
         %l++;
         if (%l >= %m && %l > %n)
         {
            if (%matchPos $= "")
               %matchPos = (%k - %m + 1) SPC %j;
            %n = %l;
         }
      }
      else
         %l = 0;
   }

   if (%matchPos !$= "")
      return  %matchPos SPC %n + 1 SPC "v";

   %size = BejeweledMinigame.numCols - 1;

   %l = 0;
   for (%k = 0; %k < %size; %k++)
   {
      if (%this.getGem(%i, %k) == %this.getGem(%i, %k + 1))
      {
         %l++;
         if (%l >= %m && %l > %n)
         {
            if (%matchPos $= "")
               %matchPos = %i SPC (%k - %m + 1);
            %n = %l;
         }
      }
      else
         %l = 0;
   }
   
   if (%matchPos !$= "")
      return %matchPos SPC %n + 1 SPC "h";

   return "";
}

//not updated for using extra lines
function BejeweledMinigame::insertGemsToMatch(%this, %gemsCount)
{
   %g = 0; 
   while (%g < %gemsCount) 
   {
      %i = getRandom(3, BejeweledMinigame.numRows - 1);
      %j = getRandom(BejeweledMinigame.numCols - 1);
      %oldGem = %this.getGem(%i, %j);

      if (%this.setRndGem(%i, %j, true))
         %g++;
      else
         %this.setGem(%oldGem, %i, %j);
   }
}

function BejeweledMinigame::playerSwap(%this, %i1, %j1, %i2, %j2)
{
   %match = "";
   if (%this.swap(%i1, %j1, %i2, %j2))
   {
      %match = %this.getMatch(%i1, %j1);
      
      if (%match $= "")   
      {
         %match = %this.getMatch(%i2, %j2);

         if (%match $= "")   
            %this.swap(%i1, %j1, %i2, %j2);
      }
      else
         %this.addGemToCheck(%i2, %j2);
   }

   if (%match !$= "")
   {
      %this.pushProcessingMatch(%match);
      BejeweledGui.animMatchBlink(%match);
   }
   else
      return false;
   
   return true;
}

function BejeweledMinigame::playerTwist(%this, %i, %j)
{
   if (!%this.twist(%i, %j))
      return false;

   %this.addGemToCheck(%i, %j);
   %this.addGemToCheck(%i, %j + 1);
   %this.addGemToCheck(%i + 1, %j + 1);
   %this.addGemToCheck(%i + 1, %j);

  BejeweledGui.animTwist(%i, %j);
   
  return true;
}

function BejeweledMinigame::onAnimTwistDone(%this)
{
   %this.checkGems();   
}

function BejeweledMinigame::onAnimMatchBlinkDone(%this)
{
   %match = %this.popProcessingMatch();
   %iM = getWord(%match, 0);
   %jM = getWord(%match, 1);
   %n = getWord(%match, 2);

   if (getWord(%match, 3) $= "v")
   {
      for (%i = %iM + %n - 1; %i >= %n; %i--)
         %this.setGem(%this.getGem(%i - 3, %jM), %i, %jM); 

      %this.cleanMatrixRect(0, %jM, %n, 1);

      if (%this.gameMode $= "Swap")
      {
         %gemToMatchNeeded = true;   
         for (%i = %iM + %n - 1; %i >= %n; %i--)
         {
            if (%this.matchOnSwap(%i, %jM))
               %gemToMatchNeeded = false;
         }
      }
      else
         %gemToMatchNeeded = false;

      for (%i = 0; %i < %n; %i++)
         %this.setRndGem(%i, %jM, %gemToMatchNeeded);
//         %gemToMatchNeeded = (!%this.setRndGem(%i, %jM, %gemToMatchNeeded) && %gemToMatchNeeded);
         
      %this.pushProcessingMatch(%match SPC (%iM + 2));
   }
   else
   {
      for (%i = %iM; %i > 0; %i--)
         for (%j = %jM; %j < %jM + %n; %j++)
            %this.setGem(%this.getGem(%i - 1, %j), %i, %j); 
      
      %this.cleanMatrixRect(0, %jM, 1, %n);

      if (%this.gameMode $= "Swap")
      {
         %gemToMatchNeeded = true;   
         for (%i = %iM; %i > 0; %i--)
            for (%j = %jM; %j < %jM + %n; %j++)
            {
               if (%this.matchOnSwap(%i, %j))
                  %gemToMatchNeeded = false;
            }
      }
      else
         %gemToMatchNeeded = false;

      for (%j = %jM; %j < %jM + %n; %j++)
         %this.setRndGem(0, %j, %gemToMatchNeeded);
//         %gemToMatchNeeded = (!%this.setRndGem(0, %j, %gemToMatchNeeded) && %gemToMatchNeeded);
         
      %this.pushProcessingMatch(%match SPC %iM SPC %jM);
   }

   BejeweledGui.animMatchFall(%match);
}

function BejeweledMinigame::pushProcessingMatch(%this, %procMatch)
{
   //echo(%procMatch SPC "PUSHED by" SPC %method);
   %this.matchStack[%this.matchStackCount] = %procMatch;
   %this.matchStackCount++;
}

function BejeweledMinigame::popProcessingMatch(%this)
{
   %this.matchStackCount--;
   //echo(%this.matchStack[%this.matchStackCount] SPC "POPPED by" SPC %method);
   return %this.matchStack[%this.matchStackCount];
}

function BejeweledMinigame::addGemToCheck(%this, %i, %j)
{
   if (%this.gemsToCheck $= "")
      %this.gemsToCheck = %i SPC %j;
   else
      %this.gemsToCheck = %this.gemsToCheck SPC %i SPC %j;
}

function BejeweledMinigame::checkGems(%this)
{
   %k = 0; 
   %count = getWordCount(%this.gemsToCheck);
   
   while (%k < %count)
   {
      %match = %this.getMatch(getWord(%this.gemsToCheck, %k), getWord(%this.gemsToCheck, %k + 1));
      %k += 2;
      
      if (%match !$= "")
      {
         %this.pushProcessingMatch(%match);
         BejeweledGui.animMatchBlink(%match);
         break;
      }
      
   }
   
   %this.gemsToCheck = getWords(%this.gemsToCheck, %k);
}
   
function BejeweledMinigame::onAnimMatchFallDone(%this)
{
   while (true)
   {
      if (%this.matchStackCount <= 0)
      {
         %this.checkGems();
         break;
      }
      
      %procMatch = %this.popProcessingMatch();
      
      if (getWordCount(%procMatch) == 4)
      {
         %this.pushProcessingMatch(%procMatch);
         BejeweledGui.animMatchBlink(%procMatch);
      }

      %iM = getWord(%procMatch, 0);
      %jM = getWord(%procMatch, 1);
      %n = getWord(%procMatch, 2);
      %newMatch = "";

      if (getWord(%procMatch, 3) $= "v")
      {
         %iC = getWord(%procMatch, 4);
      
         for (%i = %iC; %i >= %n; %i--)
         {
            if (%newMatch !$= "")
            {
               %procMatch = setWord(%procMatch, 4, %i);
               %this.pushProcessingMatch(%procMatch);
               break;
            }
            %newMatch = %this.getMatch(%i, %jM);
         }
      }
      else
      {
         %iC = getWord(%procMatch, 4);
         %jC = getWord(%procMatch, 5);

         for (%i = %iC; %i > 0; %i--)
         {
            for (%j = %jC; %j < %jM + %n; %j++)
            {
               if (%newMatch !$= "")
               {
                  %procMatch = setWord(%procMatch, 4, %i);
                  %procMatch = setWord(%procMatch, 5, %j);
                  %this.pushProcessingMatch(%procMatch);
                  break;
               }
               %newMatch = %this.getMatch(%i, %j);
            }
            if (%newMatch !$= "")
               break;
         }
      }

      if (%newMatch !$= "")   
      {
         %this.pushProcessingMatch(%newMatch);
         BejeweledGui.animMatchBlink(%newMatch);
         break;
      }
   }
   
   %randomSound = getRandom(3) + 1;
   sfxPlay(ObjectsMovingSound@%randomSound@BejeweledMinigame);
}

function BejeweledGui::onResize(%this)
{
   %this.onResizeHelper();
   
   Canvas.setWidescreen(MinigameRefCenter, 2000, true);
}

function BejeweledGui::onResizeHelper(%this)
{
   %this.xScale = getWord(BejeweledGui.getExtent(), 0)/800;
   %this.yScale =  getWord(BejeweledGui.getExtent(), 1)/600; 
   %this.x0 = mRound(getWord(%this.boardPos, 0) * %this.xScale);
   %this.y0 = mRound(getWord(%this.boardPos, 1) * %this.yScale);
   %this.gemWidth = mRound(getWord(%this.gemExtent, 0) * %this.xScale);
   %this.gemHeight = mRound(getWord(%this.gemExtent, 1) * %this.yScale);
}

function BejeweledGui::init(%this)
{   
   %this.onResize();   

   if (%this.gemBitmapMatrix[0,0] $= "")
   {
      %x0 = %this.x0;
      %y0 = %this.y0;
      %gemWidth = %this.gemWidth;
      %gemHeight = %this.gemHeight;

      %extent = mRound(%gemWidth) SPC mRound(%gemHeight);

      for (%i = 0; %i < BejeweledMinigame.numRows; %i++)
         for (%j = 0; %j < BejeweledMinigame.numCols; %j++)
         {
            %gemBitmap = new GuiBitmapCtrl() {
               canSaveDynamicFields = "0";
               Enabled = "1";
               isContainer = "0";
               HorizSizing = "relative";
               VertSizing = "relative";
               Position = (%x0 + mRound(%j*%gemWidth)) SPC (%y0 + mRound(%i*%gemHeight));
                  x0 = (getWord(%this.boardPos, 0) + %j*getWord(%this.gemExtent, 0)); //this value must be always multiplied by yScale
                  y0 = (getWord(%this.boardPos, 1) + %i*getWord(%this.gemExtent, 0)); //this value must be always multiplied by yScale
               Extent =  %extent;
               MinExtent = "2 2";
               canSave = "1";
               Visible = "1";
               hovertime = "1000";
               alpha = "1";
               color = "255 255 255 255";
               unitClip = "0 0 1 1";
               bitmap = "scriptsAndAssets/data/ui/minigame/bejeweled/"@playMinigameDlg.currentLevel@"/Gem"@BejeweledMinigame.getGem(%i,%j);
               wrap = "0";
            };
         
            %this.gemBitmapMatrix[%i, %j] = %gemBitmap;   
            %this.add(%gemBitmap);
         }

      if (BejeweledMinigame.gameMode $= "Swap")
      {
         for (%i = 0; %i < BejeweledMinigame.numRows; %i++)
            for (%j = 0; %j < BejeweledMinigame.numCols; %j++)
            {
               %gemButton = new GuiBitmapButtonCtrl() {
                  canSaveDynamicFields = "0";
                  Enabled = "1";
                  isContainer = "0";
                  HorizSizing = "relative";
                  VertSizing = "relative";
                  Position = (%x0 + mRound(%j*%gemWidth)) SPC (%y0 + mRound(%i*%gemHeight));
                  Extent = %extent;
                  MinExtent = "2 2";
                  canSave = "1";
                  Visible = "1";
                  hovertime = "1000";
                  alpha = "1";
                  color = "255 255 255 255";
                  unitClip = "0 0 1 1";
                  lockMouse = "0";
                  groupNum = "-1";
                  buttonType = "PushButton";
                  useMouseEvents = "0";
                  bitmap = "";
                  command = "BejeweledGui.clickedAt("@%i@","@%j@");";
               };
            
               %this.add(%gemButton);
            }
      }
         
      %this.selBitmap = new GuiBitmapCtrl() {
         canSaveDynamicFields = "0";
         Enabled = "1";
         isContainer = "0";
         HorizSizing = "relative";
         VertSizing = "relative";
         Position = %x0 SPC %y0;
         Extent =  BejeweledMinigame.gameMode $= "Swap"? %extent : (2*%gemWidth) SPC (2*%gemHeight);
         MinExtent = "2 2";
         canSave = "1";
         Visible = BejeweledMinigame.gameMode $= "Twist";
         hovertime = "1000";
         alpha = "1";
         color = "255 255 255 255";
         unitClip = "0 0 1 1";
         bitmap = "scriptsAndAssets/data/ui/minigame/bejeweled/"@(BejeweledMinigame.gameMode)@"er";
         wrap = "0";
      };

      %this.add(%this.selBitmap);

      
      if (BejeweledMinigame.gameMode $= "Twist")
      {
         %this.twisterDragger = new GuiContainer() {
            canSaveDynamicFields = "1";
            classname = "TwisterDragger";
            Enabled = "1";
            isContainer = "0";
            HorizSizing = "relative";
            VertSizing = "relative";
            Position = %x0 SPC %y0;
            Extent = mRound(BejeweledMinigame.numCols*%gemWidth) SPC mRound(BejeweledMinigame.numRows*%gemHeight);
            MinExtent = "1 1";
            canSave = "1";
            Visible = "1";
            hovertime = "1000";
            alpha = "1";
            color = "255 255 255 255";
            unitClip = "0 0 1 1";
            lockMouse = "0";
            Margin = "0 0 0 0";
            Padding = "0 0 0 0";
            AnchorTop = "1";
            AnchorBottom = "0";
            AnchorLeft = "1";
            AnchorRight = "0";
            useMouseEvents = "1";
         };

         %this.add(%this.twisterDragger);
      }

      %this.pushToBack(BejeweledExitButton);
   }

   %this.matchSound = new SFXProfile()
      {
         filename = "scriptsAndAssets/data/ui/minigame/bejeweled/match_sound";
         description = "AudioGui";
         preload = true;
      };

   if (BejeweledMinigame.gameMode $= "Twist")
   {
      %this.twistSound = new SFXProfile()
         {
            filename = "scriptsAndAssets/data/ui/minigame/bejeweled/twist_sound";
            description = "AudioGui";
            preload = true;
         };
   }

   if (%this.stepsPerTwist $= "")
      %this.stepsPerTwist = 4;
   
   if (%this.stepsPerFall $= "")
      %this.stepsPerFall = 7;

   if (%this.stepsPerBlink $= "")
      %this.stepsPerBlink = 6; //an even number is better   
      
   %this.initSpecificGui();
   
   BejeweledMinigame.gameFinished = false;
}

function BejeweledGui::ClickedAt(%this, %i, %j)
{
   if (%this.curAnim !$= "" || %this.gemsToCheck !$= "" || %this.matchStackCount > 0 || BejeweledMinigame.gameFinished)
      return;   
   
   //Temporary, until onResize support be activated
   %this.onResizeHelper();   

   if (BejeweledMinigame.gameMode $= "Swap")
   {      
      if (%this.selectedJew $= "")
      {
         %this.selectedJew = %i SPC %j;
         %this.selBitmap.setPosition((%this.x0 + mRound(%j*%this.gemWmidth)), 
                                     (%this.y0 + mRound(%i*%this.gemHeight)));
         %this.selBitmap.visible = "1";
         return;
      }

      %iS = getWord(%this.selectedJew, 0);
      %jS = getWord(%this.selectedJew, 1);

      %this.selectedJew = "";
      %this.selBitmap.visible = "0";

      if (!BejeweledMinigame.playerSwap(%i, %j, %iS, %jS))
         sfxPlay(AudioWrongObject);
   }
   else
   {
      BejeweledMinigame.playerTwist(%i, %j);
   }
}

function BejeweledGui::animTwist(%this, %i, %j)
{
   sfxPlay(%this.twistSound);

   %this.curAnim = %i SPC %j SPC -1;
   %this.animTwistAux();
}

function BejeweledGui::animTwistAux(%this)
{
   //Temporary, until onResize support be activated
   %this.onResizeHelper();   

   %i = getWord(%this.curAnim, 0);
   %j = getWord(%this.curAnim, 1);
   %step = getWord(%this.curAnim, 2) + 1; //INCREMENT
   
   %gb = %this.gemBitmapMatrix[%i + 1, %j + 1];
   %x0 =  %gb.x0 * %this.xScale;
   %y0 =  %gb.y0 * %this.yScale;

   %xOffset = mFloor(%this.gemWidth/2);
   %yOffset = mFloor(%this.gemHeight/2);

   %a = %xOffset/0.707107; //cos(pi/4)
   %b = %yOffset/0.707107; //sin(pi/4)

   %angleOffset = 1.570796 * (%step/%this.stepsPerTwist);
   %hhPi = 0.785398;

   %angle = -3*%hhPi + %angleOffset;     
   
   %this.gemBitmapMatrix[%i, %j + 1].setPosition(mRound(%a*mCos(%angle) + %x0 - %xOffset), 
         mRound(%b*mSin(%angle) + %y0 - (%this.gemHeight - %yOffset)));

   %angle = -%hhPi + %angleOffset;    
      
   %this.gemBitmapMatrix[%i + 1, %j + 1].setPosition(mRound(%a*mCos(%angle) + %x0 - %xOffset), 
         mRound(%b*mSin(%angle) + %y0 - %yOffset));
   
   %angle = %hhPi + %angleOffset;    
      
   %this.gemBitmapMatrix[%i + 1, %j].setPosition(mRound(%a*mCos(%angle) + %x0 - (%this.gemWidth - %xOffset)),
         mRound(%b*mSin(%angle) + %y0 - %yOffset));

   %angle = %angleOffset < %hhPi? 3*%hhPi + %angleOffset : - 5*%hhPi + %angleOffset;  
      
   %this.gemBitmapMatrix[%i, %j].setPosition(mRound(%a*mCos(%angle) + %x0 - (%this.gemWidth - %xOffset)), 
         mRound(%b*mSin(%angle) + %y0 - (%this.gemHeight - %yOffset)));

   if (%step >= %this.stepsPerTwist)
   {
      %this.curAnim = "";
      BejeweledMinigame.onAnimTwistDone();
   }
   else
   {
      %this.curAnim = setWord(%this.curAnim, 2, %step);
      scheduleObjLCA(%this, "Minigame", 100, "animTwistAux");
   }
}

function BejeweledGui::animMatchBlink(%this, %match)
{
   //echo("blink" SPC %match);
   
   %randomSound = getRandom(5) + 1;
   sfxPlay(MatchSound@%randomSound@BejeweledMinigame);

   %this.curAnim = %match SPC -1;
   %this.animBlink();
}

function BejeweledGui::animBlink(%this)
{
   %step = getWord(%this.curAnim, 4) + 1;
   
   %this.setMatchVisible(%this.curAnim, %step % 2);
   
   if (%step >= %this.stepsPerBlink) 
   {
      %this.curAnim = "";
      BejeweledMinigame.onAnimMatchBlinkDone();
   }
   else
   {
      %this.curAnim = setWord(%this.curAnim, 4, %step);
      scheduleObjLCA(%this, "Minigame", 200, "animBlink");
   }
}

function BejeweledGui::setMatchVisible(%this, %match, %visible)
{
   %iM = getWord(%match, 0);
   %jM = getWord(%match, 1);
   %n = getWord(%match, 2);
   
   if (getWord(%match, 3) $= "v")
   {
      for (%i = %iM + %n - 1; %i >= %iM; %i--)
         %this.gemBitmapMatrix[%i, %jM].visible = %visible;
   }
   else
   {
      for (%j = %jM; %j < %jM + %n; %j++)
         %this.gemBitmapMatrix[%iM, %j].visible = %visible;
   }
}

function BejeweledGui::animMatchFall(%this, %match)
{   
   //echo("FALL" SPC %match);

   %n = getWord(%match, 2);
   %timeToQuit = %this.scoreMatch(%n);
   if (%timeToQuit >= 0)
   {
      %this.counter.pause = true;

      BejeweledMinigame.gameFinished = true;
      scheduleObjLCA(%this, "Minigame", %timeToQuit, "quit");
   }
      
   %this.curAnim = %match SPC -1;
   %this.animFall();
}

function BejeweledGui::animFall(%this)
{
   //Temporary, until onResize support be activated
   %this.onResizeHelper();   
   
   %iM = getWord(%this.curAnim, 0);
   %jM = getWord(%this.curAnim, 1);
   %n = getWord(%this.curAnim, 2);
   %step = getWord(%this.curAnim, 4) + 1; //INCREMENT
   %stepsPerFall = %this.stepsPerFall;
   %done = false;

   if (getWord(%this.curAnim, 3) $= "v")
   {
      for (%i = %iM + %n - 1; %i >= 0; %i--)
      {
         %gb = %this.gemBitmapMatrix[%i, %jM];
         %y = mCeil(%this.yScale*%gb.y0) - %n*%this.gemHeight + mRound(%this.gemHeight*(%step/%stepsPerFall));
         %gb.setPosition(getWord(%gb.Position, 0), %y); 
      }
      
      if (%step >= %n*%stepsPerFall)
         %done = true;
   }
   else
   {
      for (%i = %iM; %i >= 0; %i--)
         for (%j = %jM; %j < %jM + %n; %j++)
         {
            %gb = %this.gemBitmapMatrix[%i, %j];
            %y = mCeil(%this.yScale*%gb.y0) - %this.gemHeight + mRound(%this.gemHeight*(%step/%stepsPerFall));
            %gb.setPosition(getWord(%gb.Position, 0), %y); 
         }

      if (%step >= %stepsPerFall)
         %done = true;
   }

   if (%step == 0)
      %this.setMatchVisible(%this.curAnim, 1);

   if (%done)
   {
      %this.curAnim = "";
      BejeweledMinigame.onAnimMatchFallDone();
   }
   else
   {
      %this.curAnim = setWord(%this.curAnim, 4, %step);
      scheduleObjLCA(%this, "Minigame", 100, "animFall");
   }
}

function BejeweledGui::updateGemBitmap(%this, %gem, %i, %j)
{
   %gemBitmap = BejeweledGui.gemBitmapMatrix[%i, %j];
   
   if (isObject(%gemBitmap))
      %gemBitmap.setBitmap("scriptsAndAssets/data/ui/minigame/bejeweled/"@playMinigameDlg.currentLevel@"/Gem"@%gem);
}

function BejeweledMinigame::quit(%this)
{
   BejeweledGui.quit();
}

// Quit minigame
function BejeweledGui::quit(%this)
{
   lockMouse(false);
   Canvas.showCursor();   
   
   sfxStopAll();
   
   // Widescreen support
   if(isObject(MinigameCenter))
   {
      Minigame.bringToFront(%this);
      MinigameCenter.setVisible(true);   
      Minigame.pushToBack(MinigameCenter);   
   }
   
   // Number of hints won
   Minigame.hintsGained = %this.meter.getHintsGained();   
      
   if(mFloor(Minigame.hintsGained) > 0 && BejeweledMinigame.gameFinished/* && PlayMinigameDlg.isPlayingMinigame !$= true*/)
   {
      %this.counter.pause = true;
            
      if(!%this.ConfettiIsPlaying)
      {
         if(isObject(PlayMinigameDlg))
         {            
            PlayMinigameDlgCenter.pushToBack(MinigameCircles);
            PlayMinigameDlgCenter.pushToBack(MinigameParticleFx);
            PlayMinigameDlgCenter.pushToBack(WinText);
            PlayMinigameDlgCenter.pushToBack(HintNumber);
            PlayMinigameDlgCenter.pushToBack(PMClapper);
            PlayMinigameDlgCenter.pushToBack(PMBoard);
            PlayMinigameDlgCenter.pushToBack(PMClapperStart);   
                     
            PlayMinigameDlg.bringToFront(%this);
            
            PlayMinigameDlg.setVisible(true);            
            PlayMinigameDlgCenter.setVisible(true);
         }
            
         // Play confetti
         MinigameParticleFx.ConfettiFx(15); // Play confetti for 15 secs
         %this.ConfettiIsPlaying = true;
         
         if(PlayMinigameDlg.isPlayingMinigame $= true)
            scheduleObjLCA(playMinigameDlg, "Minigame", 15*1000, "quitMinigame", 0);
         else
            // Quit a bit earlier
            scheduleObjLCA(playMinigameDlg, "Minigame", 12*1000, "quitMinigame", 0);
      }
   }
   else
   {
      Minigame.hintsGained = 0;
      
      if(isObject(PlayMinigameDlg))
         PlayMinigameDlg.bringToFront(PlayMinigameDlg.curMinigame);
      
      playMinigameDlg.quitMinigame();
   }
   
}

function TwisterDragger::onMouseMove(%this, %modifier, %worldPosition, %mouseClicks )
{
   BejeweledGui.onResizeHelper();

   %x = getWord(%worldPosition, 0) - getWord(%this.Position, 0);
   %y = getWord(%worldPosition, 1) - getWord(%this.Position, 1);
   
   // Compensate widescreen offset
   %rect2 = MinigameRefCenter.getPosition();
   %x -= getWord(%rect2,0);
   %y -= getWord(%rect2,1);   
   
   %j = mRound(%x / BejeweledGui.gemWidth) - 1;
   %i = mRound(%y / BejeweledGui.gemHeight) - 1;
   
   if (%i < 0)
      %i = 0;
   else if (%i > BejeweledMinigame.numRows - 2)
      %i = BejeweledMinigame.numRows - 2;

   if (%j < 0)
      %j = 0;
   else if (%j > BejeweledMinigame.numCols - 2)
      %j = BejeweledMinigame.numCols - 2;

   %this.i = %i;
   %this.j = %j;

   %gb = BejeweledGui.gemBitmapMatrix[%i, %j];
   BejeweledGui.selBitmap.setPosition(%gb.x0*BejeweledGui.xScale, %gb.y0*BejeweledGui.yScale);
   
   if((%this.lastCursorX != %i)||(%this.lastCursorY != %j)){
      sfxPlay(CursorSoundBejeweledMinigame);  
   }
   
   %this.lastCursorX = %i;
   %this.lastCursorY = %j;
}

function TwisterDragger::onMouseDown(%this, %modifier, %worldPosition, %mouseClicks )
{
   BejeweledGui.ClickedAt(%this.i, %this.j);
}

function BejeweledSkipButton::onMouseEnter(%this){
   if(($CurTake $= 2 && playMinigameDlg.currentLevel $= "GangsterLevel") ||
      ($CurTake $= 1 && playMinigameDlg.currentLevel $= "SciFiLevel"))
      %this.setBitmap("scriptsAndAssets/data/ui/minigame/quit_rollover.png");
   else   
      %this.setBitmap("scriptsAndAssets/data/ui/minigame/skip_rollover.png");   
}

function BejeweledSkipButton::onMouseLeave(%this){
   if(($CurTake $= 2 && playMinigameDlg.currentLevel $= "GangsterLevel") ||
      ($CurTake $= 1 && playMinigameDlg.currentLevel $= "SciFiLevel"))
      %this.setBitmap("scriptsAndAssets/data/ui/minigame/quit.png");
   else   
      %this.setBitmap("scriptsAndAssets/data/ui/minigame/skip.png");   
}

function BejeweledSkipButton::onMouseDown(%this){
   if(($CurTake $= 2 && playMinigameDlg.currentLevel $= "GangsterLevel") ||
      ($CurTake $= 1 && playMinigameDlg.currentLevel $= "SciFiLevel"))
      %this.setBitmap("scriptsAndAssets/data/ui/minigame/quit_pressed.png");
   else   
      %this.setBitmap("scriptsAndAssets/data/ui/minigame/skip_pressed.png");   
}