using System;
using System.Linq;
using Assets.Common;
using Assets.PointDistribution;

namespace Assets.AnnotationPass
{
    public class ForestPass : IAnnotationPass
    {
        public const string TreesProperty = "Trees";
        
        public double TreeRadius { get; set; } = 2;
        public double ForestRatio { get; set; } = .4;
        public double Scale { get; set; } = .01;
        public double Lacunarity { get; set; } = 1.7;
        public double Dampening { get; set; } = .7;

        public void Annotate(Map map)
        {
            var random = new Random(map.Seed + 2137); 
            var sampler = new PoissonDiskSampler(TreeRadius) { Generator = random };
            var perlin  = new PerlinNoiseGenerator
            {
                Iterations = 4,
                Scale = (float)Scale,
                Lacunarity = (float)Lacunarity,
                Decay = (float)Dampening,
                Offset = new Point(random.NextDouble() * 150, random.NextDouble() * 150)
            };
            
            var points = sampler
                .Generate(map.Size.Width, map.Size.Height)
                .Where(p => perlin.GetValue(p) < ForestRatio)
                .Select(p => new Tree { 
                    Placement = p, 
                    Site = map.Sites.Vertices.FirstOrDefault(site => PointUtils.IsPointInside(p, site.Boundary.Select(n => map.Boundaries[n]))) 
                })
                .Where(t => t.Site != null)
                .Where(t => t.Site.Tags.Contains(CommonTags.Land) && t.Site.Tags.Contains(CommonTags.Empty))
            ;
            
            map.SetProperty(TreesProperty, points.ToList());
        }
    }
}