// try to learn new normal model and save it in correspond json file.
        // the learning is in new Task and the return MODEL status field is therfore "pending".
        // does afterFinishingLearning Action after the learning finished.
        public MODEL LearnAndAddNewModel(string detectoionType, Train_Data data, Action afterFinishingLearning)
        {
            MODEL model;
            // random new model_id
            Random rnd = new Random(DateTime.Now.Millisecond);
            int    id  = rnd.Next();

            // lock L_NormalModels in order to add the new mode_id
            lock (L_NormalModels)
            {
                // check it doesn't appear already, otherwise random new id.
                while (L_NormalModels.ContainsKey(id) || System.IO.File.Exists(new MODEL()
                {
                    model_id = id
                }.FileName()))
                {
                    id = rnd.Next();
                }
                model = new MODEL()
                {
                    model_id    = id, status = MODEL.Status_Pending,
                    upload_time = DateTime.Now
                };
                L_NormalModels.Add(id, model);
            }
            // start new task of learning correlative features
            Task.Run(() => {
                try
                {
                    // learn noraml mode [that might take while], only if id not deleted yet
                    var correlation = AnomalyDetection.GetNormal(data.train_data, detectoionType, () => this.IsExist(id));
                    if (correlation == null)
                    {
                        throw new Exception();
                    }
                    // save it to json file
                    bool isSuccess = IO_Util.SaveNormalModel(model.FileName(), correlation,
                                                             new MODEL()
                    {
                        model_id = model.model_id, status = MODEL.Status_Ready, upload_time = model.upload_time
                    });

                    if (!isSuccess)
                    {
                        throw new Exception();
                    }
                    lock (L_NormalModels)
                    {
                        if (L_NormalModels.ContainsKey(id))
                        {
                            L_NormalModels[id].status = MODEL.Status_Ready;
                        }
                        else
                        {
                            // probably we won't get here since correlaion wil be null if id was deleted from L_NormalModels,
                            // because we sent the lambda ()=>this.IsExist(id) to AnomalyDetection.GetNormal
                            try { System.IO.File.Delete(new MODEL()
                                {
                                    model_id = id
                                }.FileName()); }
                            catch { }
                        }
                    }
                } catch {
                    lock (L_NormalModels)
                    {
                        if (L_NormalModels.ContainsKey(id))
                        {
                            L_NormalModels[id].status = MODEL.Status_Corrupted;
                        }
                    }
                }
                afterFinishingLearning();
            });
            // return MODEL even before the learning finished
            // { model_id = id, status = MODEL.Status_Pending, upload_time = DateTime.Now };
            return(model);
        }