using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Microsoft.Xna.Framework;
using Newtonsoft.Json;
using static TouchyTickets.Attractions.AttractionFlags;

namespace TouchyTickets.Attractions; 

[JsonConverter(typeof(Converter))]
public class AttractionModifier {

    public static readonly Dictionary<string, AttractionModifier> Modifiers = new();

    static AttractionModifier() {
        AttractionModifier.Register(new AttractionModifier("Lubricant", 200, AttractionFlags.Cars | AttractionFlags.FastCars, 1.02F, new Point(0, 4)));
        AttractionModifier.Register(new AttractionModifier("LouderMusic", 500, AttractionFlags.Relaxed, 1.03F, new Point(2, 4)));
        AttractionModifier.Register(new AttractionModifier("SmallAds", 800, AttractionFlags.Small, 1.35F, new Point(5, 4)));
        AttractionModifier.Register(new AttractionModifier("LongerQueue", 1000, AttractionFlags.All, 1.06F, new Point(1, 4)));
        AttractionModifier.Register(new AttractionModifier("Bouncer", 1500, AttractionFlags.Walking, 1.2F, new Point(3, 4)));
        AttractionModifier.Register(new AttractionModifier("OnRideCameras", 2500, AttractionFlags.FastCars, 1.1F, new Point(4, 4)));
    }

    public readonly string Name;
    public readonly long InitialPrice;
    public readonly Point Texture;
    public readonly float Multiplier;
    private readonly AttractionFlags affectedFlags;

    public AttractionModifier(string name, long initialPrice, AttractionFlags affectedFlags, float multiplier, Point texture) {
        this.Name = name;
        this.InitialPrice = initialPrice;
        this.affectedFlags = affectedFlags;
        this.Texture = texture;
        this.Multiplier = multiplier;
    }

    public bool IsAffected(Attraction attraction) {
        return (attraction.Type.Flags & this.affectedFlags) != 0;
    }

    public bool Buy(Attraction attraction) {
        var price = attraction.GetModifierPrice(this);
        if (GameImpl.Instance.Tickets < price)
            return false;
        GameImpl.Instance.Tickets -= price;
        attraction.ApplyModifier(this);
        return true;
    }

    private static AttractionModifier Register(AttractionModifier type) {
        AttractionModifier.Modifiers.Add(type.Name, type);
        return type;
    }

    public class Converter : JsonConverter<AttractionModifier> {

        public override void WriteJson(JsonWriter writer, AttractionModifier value, JsonSerializer serializer) {
            if (value != null)
                writer.WriteValue(value.Name);
        }

        public override AttractionModifier ReadJson(JsonReader reader, Type objectType, AttractionModifier existingValue, bool hasExistingValue, JsonSerializer serializer) {
            return reader.Value != null ? AttractionModifier.Modifiers[reader.Value.ToString()] : null;
        }

    }

}

[DataContract]
public class ActiveModifier {

    [DataMember]
    public readonly AttractionModifier Modifier;
    [DataMember]
    public int Amount;

    public ActiveModifier(AttractionModifier modifier, int amount) {
        this.Modifier = modifier;
        this.Amount = amount;
    }

}