public string GetFileNamePrefix
 (
     Coordinate start,
     Coordinate end,
     CoordinateInt resolution
 )
 {
     return($"region({ start.latitude },{ start.longitude })-({ end.latitude },{ end.longitude }) resolution({ resolution.latitude },{ resolution.longitude })");
 }
        public async Task GetElevationData
        (
            string filePath,
            IElevationServiceProvider serviceProvider,
            string apikey,
            Ticket <float> ticket,
            Coordinate start,
            Coordinate end,
            CoordinateInt resolution,
            int maxCoordinatesPerRequest,
            System.Action repaintWindowCallback,
            System.Action onFinish,
            bool logTraffic
        )
        {
            Debug.Log($"{ nameof(GetElevationData) }() started");

            IO.FileStream   stream = null;
            IO.StreamWriter writer = null;

            try
            {
                int skip;

                //open file stream:
                {
                    IO.FileMode fileMode;
                    if (
                        IO.File.Exists(filePath) &&
                        EditorUtility.DisplayDialog(
                            "Decide",
                            "CONTINUE: Setting must match to succeessfully continue\nOVERWRITE: data will be lost",
                            "CONTINUE",
                            "OVERWRITE"
                            )
                        )
                    {
                        fileMode = IO.FileMode.Append;
                        skip     = 0;
                        ForEachLine(
                            filePath,
                            (line) => skip++
                            );
                    }
                    else
                    {
                        fileMode = IO.FileMode.Create;
                        skip     = 0;
                    }

                    stream = new IO.FileStream(
                        filePath,
                        fileMode,
                        IO.FileAccess.Write,
                        IO.FileShare.Read,
                        4096,
                        IO.FileOptions.SequentialScan
                        );
                    writer = new IO.StreamWriter(stream);
                }

                //populate stack:
                Stack <Coordinate> coordinates = new Stack <Coordinate>();
                {
                    //NOTE: i bet this wont work for ranges overlaping -180/180 latitude crossline etc
                    Coordinate origin = new Coordinate {
                        longitude = Mathf.Min(start.longitude, end.longitude),
                        latitude  = Mathf.Min(start.latitude, end.latitude)
                    };

                    float stepX = Mathf.Abs(end.longitude - start.longitude) / (float)resolution.longitude;
                    float stepY = Mathf.Abs(end.latitude - start.latitude) / (float)resolution.latitude;
                    for (int Y = 0; Y < resolution.latitude; Y++)
                    {
                        for (int X = 0; X < resolution.longitude; X++)
                        {
                            coordinates.Push(
                                new Coordinate {
                                latitude  = origin.latitude + (float)Y * stepY,
                                longitude = origin.longitude + (float)X * stepX
                            }
                                );
                        }
                    }
                }
                int numStartingCoordinates = coordinates.Count;

                //skip entries (if applies):
                if (skip != 0)
                {
                    Debug.Log($"Skipping { skip } entries");
                    for (int i = 0; i < skip; i++)
                    {
                        coordinates.Pop();
                    }
                }

                //process stack in batches:
                List <float> elevations = new List <float>(maxCoordinatesPerRequest);
                while (coordinates.Count != 0)
                {
                    //call api:
                    {
                        //get response:
                        string response = await HttpRequest(
                            serviceProvider :            serviceProvider,
                            coordinates :                coordinates,
                            apikey :                     apikey,
                            maxCoordinatesPerRequest :   maxCoordinatesPerRequest,
                            ticket :                     ticket,
                            logTraffic :                 logTraffic
                            );

                        //
                        if (serviceProvider.ParseResponse(response, elevations))
                        {
                            if (elevations.Count != 0)
                            {
                                //write entries to file:
                                foreach (float elevation in elevations)
                                {
                                    writer.WriteLine(elevation);
                                }
                                elevations.Clear();
                            }
                            else
                            {
                                throw new System.Exception("Parsed response contains no entries");
                            }
                        }
                        else
                        {
                            throw new System.Exception("Parse failed");
                        }
                    }

                    //
                    ticket.value = 1f - ((float)coordinates.Count / (float)numStartingCoordinates);
                    repaintWindowCallback();

                    //test for abort:
                    if (ticket.invalid)
                    {
                        repaintWindowCallback();
                        throw new System.Exception("aborted");
                    }
                }

                //task done:
                ticket.value = 1f;
                repaintWindowCallback();
                Debug.Log(coordinates.Count == 0 ? "SUCCESS!" : $"ERROR, unprocessed coordinates: { coordinates.Count } )");
                await Task.CompletedTask;
            }
            catch (System.Exception ex) { Debug.LogException(ex); }
            finally
            {
                //log:
                Debug.Log($"{ nameof(GetElevationData) }() finished");

                //close streams:
                if (writer != null)
                {
                    writer.Close();
                }
                if (stream != null)
                {
                    stream.Close();
                }

                //call on finish:
                if (onFinish != null)
                {
                    onFinish();
                }
            }
        }