void OnGUI()
        {
            GUILayout.Space(10);
            GUILayout.Label("Select the lesson when opening Unity:", headerStyle);
            var newlesson = (LessonChoice)EditorGUILayout.EnumPopup("Lesson", Context.Lesson);

            //update DB if new lesson
            if ((int)newlesson > 0 && Context.Lesson != newlesson)
            {
                Context.Lesson = newlesson;
                DataLogging.UpdateChallengeInDatabase(ChallengeEventTypes.Lesson, newlesson.ToString());
            }

            if ((int)Context.Lesson < 1)
            {
                GUILayout.Label("Please select a lesson", errorStyle);
            }
            GUILayout.Space(20);

            GUILayout.Label("Select the challenge and click the appropriate button at the beginning and end:", headerStyle);
            UME.Context.Challenge = (ChallengeChoice)EditorGUILayout.EnumPopup("Challenge", Context.Challenge);

            // during challenge, add a button to stop the challenge and add buttons to start/stop group help
            if (Context.inChallenge)
            {
                GUILayout.Label("Challenge Status: Started!", okStyle);

                //button to end challenge
                if (GUILayout.Button("End of challenge"))
                {
                    Context.inChallenge      = false;
                    Context.EndChallengeTime = DataLogging.CurrentTimeStamp();
                    DataLogging.UpdateChallengeInDatabase(ChallengeEventTypes.Challenge);

                    if (Context.inGroupHelp)
                    {
                        Context.inGroupHelp      = false;
                        Context.EndGroupHelpTime = Context.EndChallengeTime;
                        GenericMenu mm = new GenericMenu();
                        foreach (KeyValuePair <string, string> item in Context.SkillSet)
                        {
                            mm.AddItem(new GUIContent(item.Value), false, GroupHelpPopUp, item.Key);
                        }
                        mm.ShowAsContext();
                    }
                }

                //Group help during challenges
                GUILayout.Space(10);
                GUILayout.Label("Group help mode during challenge", headerStyle);
                if (Context.inGroupHelp)
                {
                    GUILayout.Label("In Help Mode!", okStyle);
                    if (GUILayout.Button("End group help"))
                    {
                        Context.inGroupHelp      = false;
                        Context.EndGroupHelpTime = DataLogging.CurrentTimeStamp();

                        //pop up to select target skill
                        GenericMenu mm = new GenericMenu();
                        foreach (KeyValuePair <string, string> item in Context.SkillSet)
                        {
                            mm.AddItem(new GUIContent(item.Value), false, GroupHelpPopUp, item.Key);
                        }
                        mm.ShowAsContext();
                    }
                }
                else
                {
                    if (GUILayout.Button("Start group help"))
                    {
                        Context.inGroupHelp        = true;
                        Context.StartGroupHelpTime = DataLogging.CurrentTimeStamp();
                    }
                }
            }
            //not in challenge, just add a button to start a challenge
            else
            {
                GUILayout.Label("Challenge Status: Stopped / Not started ", errorStyle);
                if (GUILayout.Button("Start challenge"))
                {
                    if ((int)Context.Lesson > 0 && (int)Context.Challenge > 0)
                    {
                        Context.inChallenge        = true;
                        Context.StartChallengeTime = DataLogging.CurrentTimeStamp();
                        //ComSocket.Broadcast("{\"target\":\"unity\",\"cmd\":\"start_challenge\",\"params\":[]}");
                    }
                }
            }
        }
 //Skill set pop up after help mode (register selected skill in DB)
 static void GroupHelpPopUp(object obj)
 {
     DataLogging.UpdateChallengeInDatabase(ChallengeEventTypes.GroupHelp, obj.ToString());
 }
        //update challenge
        public static void UpdateChallengeInDatabase(UME.ChallengeEventTypes ev, string Params = "")
        {
            var conn = new SqliteConnection("URI=file:" + TelemetryDbPath);

            conn.Open();
            var cmd = conn.CreateCommand();

            cmd.CommandType = CommandType.Text;
            cmd.CommandText = "INSERT INTO " + ChallengeTableColumns + " VALUES (@user_id, @session_id, @lesson_id, @event, @challenge_id, @login, @start_time, @end_time, @params)";

            var evname    = "";
            var starttime = "";
            var endtime   = "";

            switch (ev)
            {
            case ChallengeEventTypes.Challenge:
                evname    = "Challenge";
                starttime = Context.StartChallengeTime;
                endtime   = Context.EndChallengeTime;
                break;

            case ChallengeEventTypes.GroupHelp:
                evname    = "GroupHelp";
                starttime = Context.StartGroupHelpTime;
                endtime   = Context.EndGroupHelpTime;
                break;

            case ChallengeEventTypes.Lesson:
                evname    = "Lesson";
                starttime = DataLogging.CurrentTimeStamp();
                break;
            }

            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "user_id", Value = Context.User
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "session_id", Value = Context.Session
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "lesson_id", Value = Context.Lesson
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "event", Value = evname
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "challenge_id", Value = (int)Context.Challenge
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "login", Value = Context.Login
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "start_time", Value = starttime
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "end_time", Value = endtime
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "params", Value = Params
            });

            cmd.ExecuteNonQuery();
            cmd.Dispose();
            cmd = null;
            conn.Close();
        }
        //Write in DB
        //static void UpdateDatabase(string Mode, string TargetName, string actionModality, string ActionType, string actionparams)
        public static void UpdateDatabase(string ActionType, string Modality, string Time = "", string Mode = "", string Tool = "", string Area = "", string Target = "", string Params = "")
        {
            var conn = new SqliteConnection("URI=file:" + TelemetryDbPath);

            conn.Open();
            var cmd = conn.CreateCommand();

            cmd.CommandType = CommandType.Text;
            cmd.CommandText = "INSERT INTO " + ActionTableColumns + " VALUES (@user_id, @session_id, @lesson_id, @challenge_id, @login, @time, @editormode, @curtool, @actionType , @keyOrMouse, @area, @target, @params)";

            if (Area == "")
            {
                Area = (UnityEditor.EditorWindow.mouseOverWindow ? UnityEditor.EditorWindow.mouseOverWindow.titleContent.text : "");
            }

            if (Mode == "")
            {
                Mode = (EditorApplication.isPlaying ? "Play" : "Edit");
            }
            if (Tool == "")
            {
                Tool = TransformToolSelected();
            }

            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "user_id", Value = Context.User
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "session_id", Value = Context.Session
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "lesson_id", Value = Context.Lesson
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "challenge_id", Value = (Context.inChallenge ? (int)Context.Challenge : -1)
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "login", Value = Context.Login
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "time", Value = (Time == "" ? DataLogging.CurrentTimeStamp() : Time)
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "editormode", Value = Mode
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "curtool", Value = Tool
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "actionType", Value = ActionType
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "keyOrMouse", Value = Modality
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "area", Value = Area
            });                                                                           //logs interface area of scene, project and hierarchy ONLY when an object in any of them is selected. Doesn't detect mouseclicks in Inspector window.
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "target", Value = Target
            });
            cmd.Parameters.Add(new SqliteParameter {
                ParameterName = "params", Value = Params
            });

            cmd.ExecuteNonQuery();
            cmd.Dispose();
            cmd = null;

            /*if( (System.DateTime.Now.Ticks - DataLogging.lastDBwrite > 3000000000) ){
             *  DataLogging.WriteDb();
             * }*/
            DataLogging.lastDBwrite = System.DateTime.Now.Ticks;
            conn.Close();
        }
        //track events in the scene and teacher help mode
        static void OnSceneGUI(SceneView sceneview)
        {
            //the following line allows all mouseUp, mouseDown and mouseDrag events to be detected, but blocks object to be selected successfully
            //HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));

            drawHelpFrame();
            var e = Event.current;

            if (e.isMouse)
            {
                //Mouse
                Vector2 initPos = e.mousePosition;
                //right click drag
                if (e.type == EventType.MouseDrag && e.button == 1)
                {
                    if ((System.DateTime.Now.Ticks - DataLogging.lastpan) > 5000000)
                    {
                        if (debug)
                        {
                            UnityEngine.Debug.Log("Right Drag performed");
                        }
                        UpdateDatabase(ActionType: "Free-Pan", Modality: "Mouse", Params: e.delta.ToString());
                        DataLogging.lastpan = System.DateTime.Now.Ticks;
                    }
                }

                if (debug)
                {
                    if (e.type == EventType.MouseUp)
                    {
                        //Left Mouse Button
                        if (e.button == 0)
                        {
                            UnityEngine.Debug.Log("Left mouse click at coordinates: " + initPos.ToString());
                        }
                        //Right Mouse Button
                        else if (e.button == 1)
                        {
                            UnityEngine.Debug.Log("Right Click");
                        }
                    }
                }
            }

            else if (e.isScrollWheel)
            {
                //Mouse Scroll wheel
                if ((System.DateTime.Now.Ticks - DataLogging.lastscroll) > 5000000)
                {
                    if (debug)
                    {
                        UnityEngine.Debug.Log("Mouse scroll wheel used " + e.delta);
                    }
                    UpdateDatabase(ActionType: "Zoom", Modality: "Mouse", Target: DataLogging.getCurrentSelectedObjectNames(), Params: e.delta.y < 0 ? "Zoom-in" : "Zoom-out");
                    DataLogging.lastscroll = System.DateTime.Now.Ticks;
                }
            }

            else
            {
                //Keyboard
                if (e != null && e.keyCode != KeyCode.None)
                {
                    //Control based special commands
                    //Undo
                    if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.Z)
                    {
                        if (debug)
                        {
                            UnityEngine.Debug.Log("Ctrl Z performed");
                        }
                        UpdateDatabase(ActionType: "Cancel", Modality: "HotKey");
                    }

                    //Redo
                    else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.Y)
                    {
                        if (debug)
                        {
                            UnityEngine.Debug.Log("Ctrl Y performed");
                        }
                        UpdateDatabase(ActionType: "Redo", Modality: "HotKey");
                    }

                    //Select all
                    else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.A)
                    {
                        if (debug)
                        {
                            UnityEngine.Debug.Log("Ctrl A performed");
                        }
                        UpdateDatabase(ActionType: "SelectAll", Modality: "HotKey", Target: DataLogging.getCurrentSelectedObjectNames());
                    }

                    //Save
                    else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.S)
                    {
                        if (debug)
                        {
                            UnityEngine.Debug.Log("Ctrl S perfomed");
                        }
                        UpdateDatabase(ActionType: "Save as", Modality: "HotKey");
                    }

                    //Duplicate
                    else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.D)
                    {
                        if (debug)
                        {
                            UnityEngine.Debug.Log("Ctrl D perfomed");
                        }
                        UpdateDatabase(ActionType: "Duplicate", Modality: "HotKey", Target: DataLogging.getCurrentSelectedObjectNames());
                    }

                    //Copy
                    else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.C)
                    {
                        if (debug)
                        {
                            UnityEngine.Debug.Log("Ctrl C perfomed");
                        }
                        UpdateDatabase(ActionType: "Copy", Modality: "HotKey", Target: DataLogging.getCurrentSelectedObjectNames());
                    }

                    //Paste
                    else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.V)
                    {
                        if (debug)
                        {
                            UnityEngine.Debug.Log("Ctrl V perfomed");
                        }
                        UpdateDatabase(ActionType: "Paste", Modality: "HotKey", Target: DataLogging.getCurrentSelectedObjectNames());
                    }

                    //Teacher help
                    else if (e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.Alpha1)
                    {
                        if (isTeacherHelping) //exit teacher help mode
                        {
                            UnityEngine.Debug.Log("");
                            isTeacherHelping = false;
                            UpdateDatabase(ActionType: "TeacherHelp", Modality: "HotKey", Params: "EndHelp " + DataLogging.opened_audio_file);
                            //sceneview.RemoveNotification();
                            DataLogging.opened_audio_file = "";
                            if (DataLogging.procaudio != null && !DataLogging.procaudio.HasExited)
                            {
                                DataLogging.procaudio.Kill();
                            }

                            //display help menu
                            GenericMenu mm          = new GenericMenu();
                            var         m_scenename = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
                            foreach (KeyValuePair <string, string> item in Context.SkillSet)
                            {
                                if (m_scenename == "challenge 1" && item.Value.Contains("Lesson1"))
                                {
                                    mm.AddItem(new GUIContent(item.Value.Replace("Lesson1/", "")), false, TeacherHelpPopUp, item.Key);
                                }
                                else if (m_scenename == "challenge 2" && item.Value.Contains("Lesson2"))
                                {
                                    mm.AddItem(new GUIContent(item.Value.Replace("Lesson2/", "")), false, TeacherHelpPopUp, item.Key);
                                }
                                else if (m_scenename == "challenge 3" && item.Value.Contains("Lesson3"))
                                {
                                    mm.AddItem(new GUIContent(item.Value.Replace("Lesson3/", "")), false, TeacherHelpPopUp, item.Key);
                                }
                            }

                            mm.AddSeparator("");
                            mm.AddSeparator("");
                            mm.AddSeparator("");
                            mm.AddSeparator("");
                            mm.AddSeparator("");

                            foreach (KeyValuePair <string, string> item in Context.SkillSet)
                            {
                                mm.AddItem(new GUIContent(item.Value), false, TeacherHelpPopUp, item.Key);
                            }

                            mm.ShowAsContext();
                        }
                        else //enter teacher help mode
                        {
                            UnityEngine.Debug.Log("Teacher help mode");
                            isTeacherHelping = true;
                            UpdateDatabase(ActionType: "TeacherHelp", Modality: "Keyboard", Params: "StartHelp");

                            //sceneview.ShowNotification(new GUIContent("Help"));
                            DataLogging.procaudio = new Process();
                            DataLogging.procaudio.StartInfo.FileName         = "arecord";
                            DataLogging.procaudio.StartInfo.WorkingDirectory = DataLogging.RecordingDbPath + "/";
                            DataLogging.opened_audio_file             = "-d 180 -f cd helpaudiorecord_" + Context.User + "_" + Context.Session + "_" + System.DateTime.Now.Ticks;
                            DataLogging.procaudio.StartInfo.Arguments = DataLogging.opened_audio_file;
                            DataLogging.procaudio.Start();
                        }
                    }

                    //Everything except control based special commands
                    else if (e != null && e.keyCode != KeyCode.None && e.keyCode != KeyCode.LeftControl &&
                             !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.Z) &&
                             !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.Y) &&
                             !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.A) &&
                             !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.S) &&
                             !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.C) &&
                             !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.V) &&
                             !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.D) &&
                             !(e.control && e.type == EventType.KeyUp && e.keyCode == KeyCode.Alpha1))
                    {
                        //Pan with arrows, maybe make it KeyUp (or maybe even let it be done by the next elseif block for KeyUp events
                        if (e.type == EventType.KeyDown)
                        {
                            if (e.keyCode == KeyCode.Delete)
                            {
                                UpdateDatabase(ActionType: "Delete", Modality: "HotKey", Target: DataLogging.last_selected_object);
                            }
                            else if (e.keyCode == KeyCode.F)
                            {
                                if (debug)
                                {
                                    UnityEngine.Debug.Log("Focus performed with F");
                                }
                                UpdateDatabase(ActionType: "Focus", Modality: "HotKey", Target: getCurrentSelectedObjectNames());
                            }

                            /*else{
                             *  if(debug) UnityEngine.Debug.Log("Key pressed in editor: " + e.keyCode);
                             *  UpdateDatabase(ActionType: "keyPressed", Modality: "Keyboard", Target: getCurrentSelectedObjectNames(), Params: e.keyCode.ToString());
                             * } */
                        }

                        //Any Key tracking on KeyUp.
                        else if (e.type == EventType.KeyUp)
                        {
                            //if(debug) UnityEngine.Debug.Log("Key Up in editor: " + e.keyCode);
                            if (e.keyCode == KeyCode.UpArrow)
                            {
                                UpdateDatabase(ActionType: "Free-pan", Modality: "Keyboard", Params: "Up");
                            }
                            else if (e.keyCode == KeyCode.DownArrow)
                            {
                                UpdateDatabase(ActionType: "Free-pan", Modality: "Keyboard", Params: "Down");
                            }
                            else if (e.keyCode == KeyCode.LeftArrow)
                            {
                                UpdateDatabase(ActionType: "Free-pan", Modality: "Keyboard", Params: "Left");
                            }
                            else if (e.keyCode == KeyCode.RightArrow)
                            {
                                UpdateDatabase(ActionType: "Free-pan", Modality: "Keyboard", Params: "Right");
                            }
                            else
                            {
                                if (debug)
                                {
                                    UnityEngine.Debug.Log("Key up in editor: " + e.keyCode);
                                }
                                UpdateDatabase(ActionType: "KeyPressed", Modality: "Keyboard", Target: getCurrentSelectedObjectNames(), Params: e.keyCode.ToString());
                            }
                        }
                    }
                }
            }
        }
        //Returns initial and final values of the current property being modified
        static UnityEditor.UndoPropertyModification[] OnPropertyModification(UnityEditor.UndoPropertyModification[] modifications)
        {
            var m_params = "";

            //if new group of property change, write previous group in DB
            if (DataLogging.current_action_group != Undo.GetCurrentGroup())
            {
                if (DataLogging.current_action_group != -1)
                {
                    if (DataLogging.new_property_group != "" && DataLogging.property_group != "")
                    {
                        m_params = (DataLogging.current_action_group + "--" + DataLogging.new_property_group + "--" + DataLogging.last_action_value_in_group + "--" + DataLogging.property_group + "--" + DataLogging.first_action_value_in_group);
                        UpdateDatabase(ActionType: "ChangeProperty", Modality: (DataLogging.area_group == "Scene" ? "Mouse" : "Keyboard"), Time: DataLogging.start_time_group, Tool: DataLogging.tool_group, Area: DataLogging.area_group, Target: DataLogging.target_group, Params: m_params);
                    }
                }

                DataLogging.first_action_value_in_group = "";
                DataLogging.last_action_value_in_group  = "";
                DataLogging.property_group       = "";
                DataLogging.new_property_group   = "";
                DataLogging.current_action_group = Undo.GetCurrentGroup();
                DataLogging.target_group         = "";
                DataLogging.start_time_group     = "";
                DataLogging.tool_group           = "";

                //var transform_values = "";
                foreach (UnityEditor.UndoPropertyModification m in modifications)
                {
                    if (m.currentValue.target.ToString().Contains("UnityEngine.Transform"))
                    {
                        if (debug)
                        {
                            UnityEngine.Debug.Log(Undo.GetCurrentGroup() + "UNDO transform" + m.currentValue.target + " " + m.currentValue.propertyPath);
                        }

                        /*if (transform_values == ""){
                         *  if(UnityEditor.Selection.objects != null){
                         *      foreach(GameObject ob in UnityEditor.Selection.objects){
                         *          var comp = ob.GetComponent(typeof(UnityEngine.Transform));
                         *          transform_values += ob.name+"[P"+comp.transform.localPosition+",R"+comp.transform.localRotation+",S"+comp.transform.localScale+"]";
                         *      }
                         *  }
                         * } */
                    }
                    else
                    {
                        if (debug)
                        {
                            UnityEngine.Debug.Log("UNDO notransform" + m.currentValue.target + " " + m.currentValue.propertyPath + " " + Undo.GetCurrentGroupName() + " " + Undo.GetCurrentGroup());
                        }
                        //UpdateDatabase(ActionType: "ChangeProperty", Modality: "Inspector", Target: getCurrentSelectedObjectNames(), Params: m_params);
                    }

                    if (DataLogging.start_time_group == "")
                    {
                        DataLogging.start_time_group = DataLogging.CurrentTimeStamp();
                    }
                    if (DataLogging.target_group == "")
                    {
                        DataLogging.target_group = DataLogging.getCurrentSelectedObjectNames();
                    }
                    if (DataLogging.tool_group == "")
                    {
                        DataLogging.tool_group = DataLogging.TransformToolSelected();
                    }
                    DataLogging.first_action_value_in_group += "[" + (m.previousValue.objectReference ? m.previousValue.objectReference.ToString() : m.previousValue.value.ToString()) + "]";
                    DataLogging.last_action_value_in_group  += "[" + (m.currentValue.objectReference ? m.currentValue.objectReference.ToString() : m.currentValue.value.ToString()) + "]";
                    DataLogging.property_group    += "[" + m.currentValue.target + "--" + m.currentValue.propertyPath + "]";
                    DataLogging.area_group         = (UnityEditor.EditorWindow.mouseOverWindow != null ? UnityEditor.EditorWindow.mouseOverWindow.titleContent.text : "");
                    DataLogging.new_property_group = property_group;
                }
            }
            //during property change (relevant for transform drag and drop, or writing)
            else
            {
                DataLogging.last_action_value_in_group = "";
                DataLogging.new_property_group         = "";
                foreach (UnityEditor.UndoPropertyModification m in modifications)
                {
                    DataLogging.last_action_value_in_group += "[" + (m.currentValue.objectReference ? m.currentValue.objectReference.ToString() : m.currentValue.value.ToString()) + "]";
                    DataLogging.new_property_group         += "[" + m.currentValue.target + "--" + m.currentValue.propertyPath + "]";
                    DataLogging.area_group = (UnityEditor.EditorWindow.mouseOverWindow != null ? UnityEditor.EditorWindow.mouseOverWindow.titleContent.text : "");
                }
            }
            return(modifications);
        }