private string Copy_Timing(TimingCopierVm arg, BackgroundWorker worker, DoWorkEventArgs _)
        {
            string[] paths    = arg.ExportPath.Split('|');
            int      mapsDone = 0;

            var reader = EditorReaderStuff.GetFullEditorReaderOrNot();

            foreach (string exportPath in paths)
            {
                var editorTo   = EditorReaderStuff.GetNewestVersionOrNot(exportPath, reader);
                var editorFrom = EditorReaderStuff.GetNewestVersionOrNot(arg.ImportPath, reader);

                Beatmap beatmapTo   = editorTo.Beatmap;
                Beatmap beatmapFrom = editorFrom.Beatmap;

                Timing timingTo   = beatmapTo.BeatmapTiming;
                Timing timingFrom = beatmapFrom.BeatmapTiming;

                // Get markers for hitobjects if mode 1 is used
                List <Marker> markers = new List <Marker>();
                if (arg.ResnapMode == "Number of beats between objects stays the same")
                {
                    markers = GetMarkers(beatmapTo, timingTo);
                }

                // Rid the beatmap of redlines
                // If a greenline exists at the same time as a redline then the redline ceizes to exist
                // Else convert the redline to a greenline: Inherited = false & MpB = -100
                List <TimingPoint> removeList = new List <TimingPoint>();
                foreach (TimingPoint redline in timingTo.GetAllRedlines())
                {
                    TimingPoint greenlineHere = timingTo.GetGreenlineAtTime(redline.Offset);
                    if (greenlineHere.Offset == redline.Offset)
                    {
                        removeList.Add(redline);
                    }
                    else
                    {
                        redline.Uninherited = false;
                        redline.MpB         = -100;
                    }
                }
                foreach (TimingPoint tp in removeList)
                {
                    timingTo.TimingPoints.Remove(tp);
                }

                // Make new timing points changes
                List <TimingPointsChange> timingPointsChanges = new List <TimingPointsChange>();

                // Add redlines
                List <TimingPoint> redlines = timingFrom.GetAllRedlines();
                foreach (TimingPoint tp in redlines)
                {
                    timingPointsChanges.Add(new TimingPointsChange(tp, mpb: true, meter: true, inherited: true, omitFirstBarLine: true));
                }

                // Apply timing changes
                TimingPointsChange.ApplyChanges(timingTo, timingPointsChanges);

                if (arg.ResnapMode == "Number of beats between objects stays the same")
                {
                    redlines = timingTo.GetAllRedlines();
                    List <double> newBookmarks = new List <double>();
                    double        lastTime     = redlines.FirstOrDefault().Offset;
                    foreach (Marker marker in markers)
                    {
                        // Get redlines between this and last marker
                        TimingPoint redline = timingTo.GetRedlineAtTime(lastTime, redlines.FirstOrDefault());

                        double beatsFromLastTime = marker.BeatsFromLastMarker;
                        while (true)
                        {
                            List <TimingPoint> redlinesBetween = redlines.Where(o => o.Offset <= lastTime + redline.MpB * beatsFromLastTime && o.Offset > lastTime).ToList();

                            if (redlinesBetween.Count == 0)
                            {
                                break;
                            }

                            TimingPoint first = redlinesBetween.First();
                            double      diff  = first.Offset - lastTime;
                            beatsFromLastTime -= diff / redline.MpB;

                            redline  = first;
                            lastTime = first.Offset;
                        }

                        // Last time is the time of the last redline in between
                        double newTime = lastTime + redline.MpB * beatsFromLastTime;
                        newTime     = timingTo.Resnap(newTime, arg.Snap1, arg.Snap2, firstTp: redlines.FirstOrDefault());
                        marker.Time = newTime;

                        lastTime = marker.Time;
                    }

                    // Add the bookmarks
                    foreach (Marker marker in markers)
                    {
                        // Check whether the marker is a bookmark
                        if (marker.Object is double)
                        {
                            // Don't resnap bookmarks
                            newBookmarks.Add((double)marker.Object);
                        }
                    }
                    beatmapTo.SetBookmarks(newBookmarks);
                }
                else if (arg.ResnapMode == "Just resnap")
                {
                    // Resnap hitobjects
                    foreach (HitObject ho in beatmapTo.HitObjects)
                    {
                        ho.ResnapSelf(timingTo, arg.Snap1, arg.Snap2, firstTp: redlines.FirstOrDefault());
                        ho.ResnapEnd(timingTo, arg.Snap1, arg.Snap2, firstTp: redlines.FirstOrDefault());
                    }

                    // Resnap greenlines
                    foreach (TimingPoint tp in timingTo.GetAllGreenlines())
                    {
                        tp.ResnapSelf(timingTo, arg.Snap1, arg.Snap2, firstTP: redlines.FirstOrDefault());
                    }
                }
                else
                {
                    // Don't move objects
                }

                // Save the file
                editorTo.SaveFile();

                // Update progressbar
                if (worker != null && worker.WorkerReportsProgress)
                {
                    worker.ReportProgress(++mapsDone * 100 / paths.Length);
                }
            }

            // Make an accurate message
            string message = $"Successfully copied timing to {mapsDone} {(mapsDone == 1 ? "beatmap" : "beatmaps")}!";

            return(message);
        }