using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Verse;
using Verse.AI;
using Verse.Sound;
using RimWorld.SquadAI;
using Verse.Noise;

namespace RimWorld{
public enum PsychicDroneLevel : byte
{
	None,

	GoodMedium,

	BadLow,
	BadMedium,
	BadHigh,
	BadExtreme
}


class Building_PsychicEmanator : Building_CrashedShipPart
{
	//Working vars
	private int					ticksToInsanityPulse;
	private int					ticksToIncreaseDroneLevel;
	public PsychicDroneLevel	droneLevel = PsychicDroneLevel.BadLow;

	//Constants
	private const int			DroneLevelIncreaseInterval = GenDate.TicksPerDay * 5;
    private static readonly		IntRange InsanityPulseInterval = new IntRange( GenDate.TicksPerDay * 2, GenDate.TicksPerDay *5);
    private const int			AnimalInsaneRadius = 25;

    //Properties
    protected override float PlantHarmRange
    {
        get
        {
            return Mathf.Min(3f + 20f * ((float)age / GenDate.TicksPerDay), 20f);
        }
    }

    public override void SpawnSetup()
    {
        base.SpawnSetup();

        ticksToInsanityPulse = InsanityPulseInterval.RandomInRange;
		ticksToIncreaseDroneLevel = DroneLevelIncreaseInterval;

		SoundDefOf.PsychicPulseGlobal.PlayOneShotOnCamera();
    }

    public override void ExposeData()
    {
        base.ExposeData();

        Scribe_Values.LookValue(ref ticksToInsanityPulse, "ticksToInsanityPulse");
        Scribe_Values.LookValue(ref ticksToIncreaseDroneLevel, "ticksToIncreaseDroneLevel");
        Scribe_Values.LookValue(ref droneLevel, "droneLevel");
    }

    public override string GetInspectString()
    {
        StringBuilder str = new StringBuilder();
        str.AppendLine(base.GetInspectString());

		string droneLevelString = "Error";
		switch( droneLevel )
		{
			case PsychicDroneLevel.BadLow: droneLevelString = "PsychicDroneLevelLow".Translate();
				break;
			case PsychicDroneLevel.BadMedium: droneLevelString = "PsychicDroneLevelMedium".Translate();
				break;
			case PsychicDroneLevel.BadHigh: droneLevelString = "PsychicDroneLevelHigh".Translate();
				break;
			case PsychicDroneLevel.BadExtreme: droneLevelString = "PsychicDroneLevelExtreme".Translate();
				break;
		}

		str.AppendLine("PsychicDroneLevel".Translate( droneLevelString ) );

        return str.ToString();
    }

    public override void Tick()
    {
        base.Tick();

        ticksToInsanityPulse--;
		if (ticksToInsanityPulse <= 0 )
		{
			DoAnimalInsanityPulse();
			ticksToInsanityPulse = InsanityPulseInterval.RandomInRange;
		}

		ticksToIncreaseDroneLevel--;
		if( ticksToIncreaseDroneLevel <= 0 )
		{
			IncreaseDroneLevel();
			ticksToIncreaseDroneLevel = DroneLevelIncreaseInterval;
		}

		//Maybe: do single colonist insanity
		/*
		if( Find.TickManager.tickCount % 100 == 0
			&& Rand.Value < ColonistInsanityChancePer100Ticks )
			DoSingleColonistInsanity();
		 * */
    }

	/*
	private void DoSingleColonistInsanity()
	{
		Pawn colonist = Find.ListerPawns
						.FreeColonists
						.Where( pa=>!pa.Incapacitated && pa.GetStatValue( StatDefOf.PsychicSensitivity ) > 0.1f )
						.RandomElement();

		if( colonist == null )
			return;

        Find.History.AddGameEvent("LetterShipPartDroveColonistInsane".Translate(colonist.Name.nick), GameEventType.BadNonUrgent, true);

		int selector = Rand.Range(0,100);
		if( selector < 40 )
			PsychologyUtility.TryDoMentalBreak( colonist, SanityState.DazedWander );
		else
			PsychologyUtility.TryDoMentalBreak( colonist, SanityState.Berserk );

		SoundDef.Named("PsychicPulseGlobal").PlayOneShotOnCamera();
	}*/

	private void IncreaseDroneLevel()
	{
		if( droneLevel == PsychicDroneLevel.BadExtreme )
			return;

		droneLevel++;

		string letter = "LetterPsychicDroneLevelIncreased".Translate();
        Find.LetterStack.ReceiveLetter("LetterLabelPsychicDroneLevelIncreased".Translate(), letter, LetterType.BadNonUrgent);

		SoundDefOf.PsychicPulseGlobal.PlayOneShotOnCamera();
	}

    private void DoAnimalInsanityPulse()
    {
        // Find the animals to work with
        IEnumerable<Pawn> nearbyAnimals = 
			Find.ListerPawns.AllPawns.Where(p => p.RaceProps.Animal 
				&& p.Position.InHorDistOf(Position, AnimalInsaneRadius));

        // Make all animals berserk (60% chance) 
        foreach (Pawn animal in nearbyAnimals)
        {
			animal.mindState.broken.StartBrokenState( BrokenStateDefOf.Manhunter );
        }

		Messages.Message( "MessageAnimalInsanityPulse".Translate(), MessageSound.Negative );

		Find.CameraMap.shaker.DoShake( 4.0f );
		SoundDefOf.PsychicPulseGlobal.PlayOneShotOnCamera();
    }
}}
