#include <Mouse.h>
#include <Keyboard.h>

int DELAY_KEY = 20;
int DELAY_MOUSE = 20;

void setup() {
  Serial.begin(9600);
  Mouse.begin();
  Keyboard.begin();
}

void loop()
{
  char key[64];
  String text = "";

  while (Serial.available() == 0) {
    delay(1);
  }
  while (Serial.available() > 0) {
    text += (char)Serial.read();
    delay(1);
  }

  switch (text.substring(0, 1).toInt()) {
    case 0:  //       
      {
        if (text.substring(1, 2).equals("0"))DELAY_KEY = text.substring(2).toInt(); 
        else DELAY_MOUSE = text.substring(2).toInt();
        break;
      }
    case 1:  //  
      {
        Keyboard.press(text.substring(1).toInt());
        delay(DELAY_KEY);
        Keyboard.release(text.substring(1).toInt());
        delay(DELAY_KEY);
        break;
      }
    case 2:  //  
      {
        //    
        text.substring(1).toCharArray(key, text.length());

        for (int i = 0; i < text.length(); i++)
        {
          Keyboard.write(key[i]);
          delay(DELAY_KEY);
        }
        break;
      }
    case 3:  //  
      {
        Keyboard.press(text.substring(1).toInt());
        delay(DELAY_KEY);
        break;
      }
    case 4:  //  
      {
        Keyboard.release(text.substring(1).toInt());
        delay(DELAY_KEY);
        break;
      }
    case 5:  //   
      {
        long coordinate = text.substring(3).toInt();
        // x  y      
        long x = coordinate / 65535;
        long y = coordinate % 65535;

        //   / /
        if (text.substring(1, 2).equals("-"))x = -x;
        if (text.substring(2, 3).equals("-"))y = -y;

        //    
        int count_step;         
        int stepX = 127, stepY = 127;        // 
        int remainsX, remainsY;  //    

        if (abs(x) > abs(y))  //   X      Y
        {
          count_step = abs(x) / 127;
          if (count_step > 0)
          {
            if (x < 0)stepX = -127;
            
            if (y > 0)stepY = abs(y) / count_step;
            else stepY = y / count_step;

            if (abs(stepY) > 127)
            {
              if (stepY > 0)stepY = 127;
              else stepY = -127;
            }
          }
          remainsX = x % stepX;
          remainsY = y % stepY;
        }
        else
        {
          count_step = abs(y) / 127;
          if (count_step > 0)
          {
            if (y < 0)stepY = -127;
            if (x > 0)stepX = abs(x) / count_step;
            else stepX = x / count_step;

            if (abs(stepX) > 127)
            {
              if (stepX > 0)stepX = 127;
              else stepX = -127;
            }           
          }
          remainsX = x % stepX;
          remainsY = y % stepY;
        }

        for (int i = 0; i < count_step; i++)  //  
        {
          Mouse.move(stepX, stepY, 0);
          delay(5);
        }

        Mouse.move(remainsX, remainsY, 0);  //    
        delay(5);
        break;
      }
    case 6:  //   
      {
        Mouse.click(text.charAt(1));
        delay(DELAY_MOUSE);
        break;
      }
    case 7:  //   
      {
        Mouse.press(text.charAt(1));
        delay(DELAY_MOUSE);
        break;
      }
    case 8:  //   
      {
        Mouse.release(text.charAt(1));
        delay(DELAY_MOUSE);
        break;
      }
      break;
  }

}