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\":[]}");
                    }
                }
            }
        }
        //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();
        }
        //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();
        }
        //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);
        }