// gets the tile set of maps with the given coords of the center, width and height of tiling
        // and configuration for the center tile
        public static void DownloadNewTileSet(MapConfiguration config, BackgroundWorker worker)
        {
            String fileName = Directory.GetCurrentDirectory().ToString() + @"\Images\" + config.MapSetName + ".map";

            using (StreamWriter file = new StreamWriter(fileName))
            {
                Tuple <int, int> centerPoint = MapConversion.LatLongToPixelXY(config.Latitude,
                                                                              config.Longitude, config.Zoom);

                file.WriteLine(config.ImgWidth + "x" + config.ImgHeight + "|" + config.Latitude + ","
                               + config.Longitude + "|" + config.Zoom + "|" + config.Scale + "|" + config.MapType);

                // center of the tiling is 0,0
                int startx = -config.TilingWidth / 2;
                int starty = -config.TilingHeight / 2;
                if (config.TilingWidth % 2 == 0)
                {
                    startx++;
                }
                if (config.TilingHeight % 2 == 0)
                {
                    starty++;
                }
                int numberDownloaded = 0;

                for (int i = startx; i <= config.TilingWidth / 2; i++)
                {
                    for (int j = starty; j <= config.TilingHeight / 2; j++)
                    {
                        if (worker != null)
                        {
                            worker.ReportProgress(numberDownloaded);
                        }

                        Tuple <double, double> newCoords = MapConversion.PixelXYToLatLong
                                                               (centerPoint.Item1 + (i * config.ImgWidth), centerPoint.Item2
                                                               + (j * config.ImgHeight), config.Zoom);
                        config.Latitude  = newCoords.Item1;
                        config.Longitude = newCoords.Item2;
                        string imageName = Fetch(config);
                        if (imageName != null)
                        {
                            file.WriteLine(i + "," + j + "|" + imageName);
                        }

                        numberDownloaded++;
                    }
                }
            }
        }
        private static void CropImage(string file, MapConfiguration config, MemoryStream inStream)
        {
            // this was done all to the documentation
            ISupportedImageFormat format = new PngFormat();
            Size      size = new Size(config.ImgWidth * config.Scale, config.ImgHeight * config.Scale);
            Rectangle crop = new Rectangle(new Point(0, config.Scale * MapConfiguration.LOGO_BLEED / 2), size);

            using (ImageFactory imageFactory = new ImageFactory(preserveExifData: true))
            {
                imageFactory.Load(inStream)
                .Crop(crop)
                .Resize(size)
                .Format(format)
                .Save(file);
            }
        }
        // pulls a single map tile from google maps returns the hash code used for the file name.
        // Will return null if the image was not downloaded
        public static String Fetch(MapConfiguration config)
        {
            String requestUrl    = "https://maps.googleapis.com/maps/api/staticmap?" + config.URLParams();
            bool   notDownloaded = true;

            HttpWebResponse response = null;

            while (notDownloaded)
            {
                HttpWebRequest request = WebRequest.CreateHttp(requestUrl);
                try
                {
                    response      = (HttpWebResponse)request.GetResponse();
                    notDownloaded = false;
                } catch (WebException ex)
                {
                    Console.WriteLine(ex.Status + " " + ex.Message);
                    Console.WriteLine("Retrying Download");
                }
            }
            Stream input = response.GetResponseStream();

            // writes to the buffer stream
            using (MemoryStream buffer = new MemoryStream())
            {
                input.CopyTo(buffer);
                //hash code generator
                SHA256Managed sha = new SHA256Managed();
                buffer.Position = 0;
                byte[] hash       = sha.ComputeHash(buffer);
                var    bufferHash = BitConverter.ToString(hash).Replace("-", String.Empty).Substring(0, 16);

                String fileName = Directory.GetCurrentDirectory().ToString() + @"\Images\" + bufferHash + ".jpg";

                if (File.Exists(fileName))
                {
                    return(bufferHash); // Already saved the file
                }

                buffer.Position = 0;
                CropImage(fileName, config, buffer);
                return(bufferHash);
            }
        }
 public static void DownloadNewTileSet(MapConfiguration config)
 {
     DownloadNewTileSet(config, null);
 }