<commit_before>﻿namespace Winium.StoreApps.Driver.EmulatorHelpers
{
    #region

    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Linq;
    using System.Threading;
    using System.Windows.Forms;

    using Microsoft.Xde.Common;
    using Microsoft.Xde.Wmi;

    using Winium.StoreApps.Common;
    using Winium.StoreApps.Common.Exceptions;

    #endregion

    internal class EmulatorController
    {
        #region Fields

        private readonly IXdeVirtualMachine emulatorVm;

        private Point cursor;

        private Size virtualScreenSize;

        #endregion

        #region Constructors and Destructors

        public EmulatorController(string emulatorName)
        {
            this.emulatorVm = GetEmulatorVm(emulatorName);
            this.cursor = new Point(0, 0);
            this.PhoneOrientationToUse = PhoneOrientation.Landscape;

            if (this.emulatorVm == null)
            {
                throw new NullReferenceException(
                    string.Format("Could not get running XDE virtual machine {0}", emulatorName));
            }

            this.PhoneScreenSize = this.emulatorVm.GetCurrentResolution();
        }

        #endregion

        #region Enums

        [Flags]
        public enum PhoneOrientation
        {
            None = 0, 

            Portrait = 1, 

            Landscape = 2, 

            PortraitUp = 5, 

            PortraitDown = 9, 

            LandscapeLeft = 18, 

            LandscapeRight = 34, 
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Current phone orientation to be used when translating phone screen coordinates into virtual machine screen coordinates.
        /// Should be set before using PhoneScreenSize or any mouse moving methods
        /// </summary>
        public PhoneOrientation PhoneOrientationToUse { get; set; }

        public Size PhoneScreenSize
        {
            get
            {
                return (this.PhoneOrientationToUse & PhoneOrientation.Landscape) == PhoneOrientation.Landscape
                           ? new Size(this.virtualScreenSize.Height, this.virtualScreenSize.Width)
                           : this.virtualScreenSize;
            }

            private set
            {
                this.virtualScreenSize = value;
            }
        }

        #endregion

        #region Public Methods and Operators

        public string GetIpAddress()
        {
            var nic = this.emulatorVm.InternalNic;
            if (nic == null)
            {
                throw new NullReferenceException("Windows Phone Emulator Internal Switch not found");
            }

            if (nic.SwitchInformation.HostIpAddress == null)
            {
                throw new NullReferenceException("Unable to determine Windows Phone Emulator IP address.");
            }

            return nic.SwitchInformation.HostIpAddress;
        }

        public void LeftButtonClick(Point? point = null)
        {
            if (point.HasValue)
            {
                this.MoveCursorTo(point.Value);
            }

            this.LeftButtonDown();
            this.LeftButtonUp();
        }

        public void LeftButtonDown()
        {
            var hold = new MouseEventArgs(MouseButtons.Left, 0, this.cursor.X, this.cursor.Y, 0);
            this.emulatorVm.SendMouseEvent(hold);
        }

        public void LeftButtonUp()
        {
            var release = new MouseEventArgs(MouseButtons.None, 0, this.cursor.X, this.cursor.Y, 0);
            this.emulatorVm.SendMouseEvent(release);
        }

        public void MoveCursorTo(Point phonePoint)
        {
            var xdePoint = this.TranslatePhoneToVirtualmachinePoint(phonePoint);
            this.cursor = xdePoint;
        }

        public void PerformGesture(IGesture gesture)
        {
            // TODO Works only for default portrait orientation, need to take orientation into account
            var array = gesture.GetScreenPoints().ToArray();

            foreach (var point in array.Take(array.Length - 1))
            {
                this.MoveCursorTo(point);
                this.LeftButtonDown();
                Thread.Sleep(gesture.PeriodBetweenPoints);
            }

            this.MoveCursorTo(array.Last());
            this.LeftButtonUp();
        }

        public bool PhonePointVisibleOnScreen(Point phonePoint)
        {
            var phoneScreen = new Rectangle(new Point(0, 0), this.PhoneScreenSize);
            return phoneScreen.Contains(phonePoint);
        }

        public string TakeScreenshot()
        {
            var size = this.emulatorVm.GetCurrentResolution();
            var screen = this.emulatorVm.GetScreenShot(0, 0, size.Width, size.Height);

            var base64 = ImageToBase64String(screen, ImageFormat.Png);<commit_msg>Use cached screen size to speed up Screenshot command<commit_after>﻿namespace Winium.StoreApps.Driver.EmulatorHelpers
{
    #region

    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Linq;
    using System.Threading;
    using System.Windows.Forms;

    using Microsoft.Xde.Common;
    using Microsoft.Xde.Wmi;

    using Winium.StoreApps.Common;
    using Winium.StoreApps.Common.Exceptions;

    #endregion

    internal class EmulatorController
    {
        #region Fields

        private readonly IXdeVirtualMachine emulatorVm;

        private Point cursor;

        private Size virtualScreenSize;

        #endregion

        #region Constructors and Destructors

        public EmulatorController(string emulatorName)
        {
            this.emulatorVm = GetEmulatorVm(emulatorName);
            this.cursor = new Point(0, 0);
            this.PhoneOrientationToUse = PhoneOrientation.Landscape;

            if (this.emulatorVm == null)
            {
                throw new NullReferenceException(
                    string.Format("Could not get running XDE virtual machine {0}", emulatorName));
            }

            this.PhoneScreenSize = this.emulatorVm.GetCurrentResolution();
        }

        #endregion

        #region Enums

        [Flags]
        public enum PhoneOrientation
        {
            None = 0, 

            Portrait = 1, 

            Landscape = 2, 

            PortraitUp = 5, 

            PortraitDown = 9, 

            LandscapeLeft = 18, 

            LandscapeRight = 34, 
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Current phone orientation to be used when translating phone screen coordinates into virtual machine screen coordinates.
        /// Should be set before using PhoneScreenSize or any mouse moving methods
        /// </summary>
        public PhoneOrientation PhoneOrientationToUse { get; set; }

        public Size PhoneScreenSize
        {
            get
            {
                return (this.PhoneOrientationToUse & PhoneOrientation.Landscape) == PhoneOrientation.Landscape
                           ? new Size(this.virtualScreenSize.Height, this.virtualScreenSize.Width)
                           : this.virtualScreenSize;
            }

            private set
            {
                this.virtualScreenSize = value;
            }
        }

        #endregion

        #region Public Methods and Operators

        public string GetIpAddress()
        {
            var nic = this.emulatorVm.InternalNic;
            if (nic == null)
            {
                throw new NullReferenceException("Windows Phone Emulator Internal Switch not found");
            }

            if (nic.SwitchInformation.HostIpAddress == null)
            {
                throw new NullReferenceException("Unable to determine Windows Phone Emulator IP address.");
            }

            return nic.SwitchInformation.HostIpAddress;
        }

        public void LeftButtonClick(Point? point = null)
        {
            if (point.HasValue)
            {
                this.MoveCursorTo(point.Value);
            }

            this.LeftButtonDown();
            this.LeftButtonUp();
        }

        public void LeftButtonDown()
        {
            var hold = new MouseEventArgs(MouseButtons.Left, 0, this.cursor.X, this.cursor.Y, 0);
            this.emulatorVm.SendMouseEvent(hold);
        }

        public void LeftButtonUp()
        {
            var release = new MouseEventArgs(MouseButtons.None, 0, this.cursor.X, this.cursor.Y, 0);
            this.emulatorVm.SendMouseEvent(release);
        }

        public void MoveCursorTo(Point phonePoint)
        {
            var xdePoint = this.TranslatePhoneToVirtualmachinePoint(phonePoint);
            this.cursor = xdePoint;
        }

        public void PerformGesture(IGesture gesture)
        {
            // TODO Works only for default portrait orientation, need to take orientation into account
            var array = gesture.GetScreenPoints().ToArray();

            foreach (var point in array.Take(array.Length - 1))
            {
                this.MoveCursorTo(point);
                this.LeftButtonDown();
                Thread.Sleep(gesture.PeriodBetweenPoints);
            }

            this.MoveCursorTo(array.Last());
            this.LeftButtonUp();
        }

        public bool PhonePointVisibleOnScreen(Point phonePoint)
        {
            var phoneScreen = new Rectangle(new Point(0, 0), this.PhoneScreenSize);
            return phoneScreen.Contains(phonePoint);
        }

        public string TakeScreenshot()
        {
            var size = this.virtualScreenSize;
            var screen = this.emulatorVm.GetScreenShot(0, 0, size.Width, size.Height);

            var base64 = ImageToBase64String(screen, ImageFormat.Png);
{'fraction_non_alphanumeric': 0.07488315383052226, 'fraction_numerical': 0.005080268238162975, 'mean_word_length': 1.7160596026490067, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3633906', 'n_tokens_mistral': 2557, 'n_tokens_neox': 2386, 'n_words': 589}