using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;

/*
 *  TODO
 *  Get new UI in
 */

public enum JOB_TYPE
{
    TEND_FARM,
    TEND_SHOP,
    BUILD_FARM,
    BUILD_SHOP,
    BUILD_HOUSE,
    UPGRADE,
    WITNESS_RITUAL,
    DEMOLISH
}

public enum SMITE_TYPE
{
    FIRE = 0,
    FLOOD,
    LOCUST
}

public enum PLAY_STATE
{
    NORMAL,
    PLACING_BUILDING,
    BUYING_VILAGER,
    SMITE,
    SACRIFICING,
}

public class Job
{
    public Vector3  goal_point;

    public Building job_building;
    public Building finished_building;
    public JOB_TYPE job_type;
    public float    job_timer;

    public int      max_people;
    public int      assigned_count;
    public Person[] assigned_people;
}

public class TownManager : MonoBehaviour {

    public static TownManager tm;

    public float food_generation_timer; 
    public float money_generation_timer;
    public float food_consumtion_per_person;
    public int people_per_house;

    public GameObject house_prefab;
    public GameObject farm_prefab;

    public GameObject shop_prefab;
    public GameObject construction_prefab;

    public GameObject builder_prefab;
    public GameObject merchant_prefab;
    public GameObject farmer_prefab;

    public GameObject placing_object;

    public GameObject hot_prefab;
    public BUILDING_TYPE placing_type;

    public int total_food = 25;
    public int total_money = 500;

    public List<Person> people = new List<Person>();
    public List<Building> buildings = new List<Building>();
    public List<Job> current_jobs = new List<Job>();

    public RectTransform buy_buttons;
    public RectTransform upgrade_button;
    public Building buy_house;

    public int house_cost = 5;
    public int farm_cost = 3;
    public int shop_cost = 15;

    public GameObject sacrifice_panel;
    public GameObject sacrifice_entry;
    public float sacrifice_timer;
    public float smite_timer = 50;
    public GameObject[] sacrifice_entries;
    public SMITE_TYPE current_smite;

    public PLAY_STATE current_state;

    public float god_happiness = 1f;
    public int piety_demand;
    public int charity_demand;
    public int work_demand;

    public AudioSource construction;
    public AudioSource fire;
    public AudioSource locusts;
    public AudioSource man_scream;
    public AudioSource rain;
    public AudioSource splat;
    public AudioSource village_screams;
    public AudioSource woman_scream;
    public AudioSource place_building ;

    public AudioSource gong;
    public AudioSource angry_music;
    public AudioSource happy_music;

    public ParticleSystem locust_particles;
    public ParticleSystem flood_paritcles;
    public ParticleSystem fire_particles;

    public Text food_label;
    public Text money_label;
    public Text population_label;

    public bool people_chosen = false;

    public GameObject pause_panel;

    public GameObject splat_sprite;

    public void PauseGame()
    {
        pause_panel.SetActive(true);
    }
    public void UnpauseGame()
    {
        pause_panel.SetActive(false);
    }

    public void Quit()
    {
        Application.Quit();
    }

    void Awake()
    {
        tm = this;
        placing_object.SetActive(false);
    }

    int GetMaxHeadCount()
    {
        int result = 0;
        for ( int i = 0 ; i < buildings.Count ; ++i )
        {
            Building b = buildings[i];
            if( b.type == BUILDING_TYPE.HOUSE && b.level > 0 )
            {
                result += people_per_house * b.level;
            }
        }

        return result;
    }

    int GetFreeHeadCount()
    {
        int result = GetMaxHeadCount() - people.Count;

        return result;
    }

	// Update is called once per frame
	void Update () 
    {
        Resolution current_res = Screen.currentResolution;
        float meters_to_pixels = (Camera.main.orthographicSize * 4) / current_res.height;

        food_label.text= "Food: " + total_food;
        population_label.text= "Population: " + people.Count + " / " + GetMaxHeadCount();
        money_label.text= "Gold: " + total_money;

        if ( buy_house )
        {
            buy_buttons.position = Camera.main.WorldToScreenPoint(buy_house.transform.position) + 
                Vector3.up * (1f / meters_to_pixels);
            upgrade_button.position = Camera.main.WorldToScreenPoint(buy_house.transform.position);
        }

        if (current_state != PLAY_STATE.SACRIFICING )
        {
            smite_timer -= Time.deltaTime;
            sacrifice_timer -= Time.deltaTime;
            god_happiness -= 0.002f * Time.deltaTime;
            god_happiness = Mathf.Clamp01(god_happiness);
        }


        //update gamestate from player input
        switch ( current_state )
        {

            case PLAY_STATE.NORMAL:
            {


                if ( smite_timer < 0 )
                {
                    smite_timer = 100;

                    if ( god_happiness < 0.8f )
                    {
                        float smite_chance = 
                            Mathf.Lerp(0, 0.9f, (0.8f-god_happiness) / 0.8f);
                        if ( Random.value < smite_chance )
                        {
                            current_state = PLAY_STATE.SMITE;
                            current_smite = (SMITE_TYPE)Random.Range(0, 3);
                        }
                    }
                }


                if ( god_happiness == 0 || 
                        (people.Count == 0 && buildings.Count == 0))
                {
                    Application.LoadLevel("main_menu");
                    return;
                }

                if ( sacrifice_timer < 0 )
                {
                    sacrifice_panel.SetActive(true);
                    gong.Play();

                    happy_music.DOFade(0, 2);
                    angry_music.DOFade(1, 2);

                    sacrifice_panel.transform.SetAsLastSibling();

                    int total_piety = 0;
                    int total_charity = 0;
                    int total_work = 0;
                    for ( int i = 0 ; i < people.Count ; ++i )
                    {
                        total_piety += people[i].piety;
                        total_charity += people[i].charity;
                        total_work += people[i].work_ethic;
                    }

                    piety_demand += Random.Range(0, total_piety / 2);
                    charity_demand += Random.Range(0, total_charity / 2);
                    work_demand += Random.Range(0, total_work / 2);

                    sacrifice_panel.transform.FindChild("DemandsText").GetComponent<Text>().text = 
                        "God Demands\n" + 
                        piety_demand + " Piety\n" +
                        charity_demand + " Charity\n" +
                        work_demand + " Work Ethic\n";

                    current_state = PLAY_STATE.SACRIFICING;

                    Vector3 pos = sacrifice_entry.transform.position;

                    sacrifice_entries = new GameObject[people.Count];

                    

                    for ( int i = 0 ; i < people.Count ; ++i )
                    {
                        Person p = people[i];

                        GameObject new_entry = (GameObject)Instantiate(sacrifice_entry, pos, Quaternion.identity);
                        new_entry.transform.SetParent(sacrifice_entry.transform.parent);
                        new_entry.SetActive(true);
                        new_entry.transform.FindChild("0").GetComponent<Text>().text = p.full_name;
                        new_entry.transform.FindChild("1").GetComponent<Text>().text = p.piety.ToString();
                        new_entry.transform.FindChild("2").GetComponent<Text>().text = p.work_ethic.ToString();
                        new_entry.transform.FindChild("3").GetComponent<Text>().text = p.charity.ToString();
                        new_entry.transform.FindChild("4").GetComponent<Text>().text = p.skill.ToString();
                        new_entry.transform.FindChild("5").GetComponent<Text>().text = p.work_type.ToString();
                        sacrifice_entries[i] = new_entry;
                        pos.y -= 20;
                    }

                    FindObjectOfType<ScrollController>().height = people.Count * 20;
                }

                if ( Input.GetMouseButtonDown(0) )
                {
                    Vector3 mouse_pos = Input.mousePosition;
                    Ray r = Camera.main.ScreenPointToRay(mouse_pos);

                    RaycastHit info;
                    if ( Physics.Raycast(r, out info) )
                    {
                        Building b = info.collider.gameObject.GetComponent<Building>();
                        if ( b != null )
                        {
                            if ( b.level != 0 )
                            {
                                buy_house = b;
                                upgrade_button.GetChild(0).GetComponent<Text>().text = "Upgrade (" + b.upgrade_cost + ")";
                                current_state = PLAY_STATE.BUYING_VILAGER;
                                if ( b.type == BUILDING_TYPE.HOUSE )
                                {
                                    buy_buttons.position = Camera.main.WorldToScreenPoint(buy_house.transform.position) + 
                                        Vector3.up * (1f / meters_to_pixels);
                                    buy_buttons.localScale = Vector3.zero;
                                    buy_buttons.DOScale(1, 0.5f).SetEase(Ease.OutCubic);
                                }

                                upgrade_button.position = Camera.main.WorldToScreenPoint(buy_house.transform.position);
                                upgrade_button.DOScale(1, 0.5f).SetEase(Ease.OutCubic);
                            }
                        }
                    }

                }
            } break;
            case PLAY_STATE.SMITE:
            {
                float anger = 1 - god_happiness;
                int possible_buildings = (int)((float)buildings.Count * anger);
                if ( possible_buildings > 0 )
                {
                    int building_count = Random.Range(1, possible_buildings);

                    for ( int i = 0 ; i < building_count ; ++ i )
                    {
                        int building_index = Random.Range(0, buildings.Count);
                        DestroyBuilding(buildings[building_index]);
                    }

                    switch ( current_smite )
                    {
                        case SMITE_TYPE.FIRE:
                        {
                            fire_particles.Play();
                            fire.Play();
                        } break;
                        case SMITE_TYPE.FLOOD:
                        {
                            flood_paritcles.Play();
                            rain.Play();
                        } break;
                        case SMITE_TYPE.LOCUST:
                        {
                            locusts.Play();
                            locust_particles.Play();
                        } break;
                    }
                }

                current_state = PLAY_STATE.NORMAL;
            } break;
            case PLAY_STATE.BUYING_VILAGER:
            {
                if ( Input.GetMouseButtonDown(0) && 
                        EventSystem.current.currentSelectedGameObject == null )
                {
                    current_state = PLAY_STATE.NORMAL;
                    buy_buttons.DOScale(0, 0.5f).SetEase(Ease.OutCubic);
                    upgrade_button.DOScale(0, 0.5f).SetEase(Ease.OutCubic);
                }
            } break;

            case PLAY_STATE.SACRIFICING:
            {
                sacrifice_timer = 100;

                if (people_chosen)
                {
                    if ( people_to_kill.Count == 0 )
                    {
                        current_state = PLAY_STATE.NORMAL;
                    }

                    Transform c_tran = Camera.main.transform;
                    Plane p = new Plane(Vector3.up, 0);
                    Ray r = new Ray(c_tran.position, c_tran.forward);

                    float dist = 0;
                    p.Raycast(r, out dist);
                    Vector3 cam_offset = c_tran.position - r.GetPoint(dist);
                    Sequence kill_sequence = DOTween.Sequence();

                    int total_demand = piety_demand + charity_demand + work_demand;
                    float missing_happiness = 1f - god_happiness;
                    float happiness_snapshot = god_happiness;

                    for (int i = 0 ; i < people_to_kill.Count ; ++i )
                    {
                        piety_demand -= people_to_kill[i].piety;
                        charity_demand -= people_to_kill[i].charity;
                        work_demand -= people_to_kill[i].work_ethic;

                        piety_demand = Mathf.Max(0, piety_demand);
                        charity_demand = Mathf.Max(0, charity_demand);
                        work_demand = Mathf.Max(0, work_demand);

                        int new_total = piety_demand + charity_demand + work_demand;
                        int improvement = total_demand - new_total;
                        float percent = (float)improvement / (float)total_demand;

                        int dumb_i = i;
                        kill_sequence.Append(c_tran.DOMove(people_to_kill[i].transform.position + cam_offset, 2f));
                        kill_sequence.Append(people_to_kill[i].transform.DOMoveY(3, 1));
                        kill_sequence.Append(people_to_kill[i].transform.DOMove(new Vector3(0, 3, 0), 1));
                        kill_sequence.Insert(4.8f * i + 3, c_tran.DOMove(new Vector3(0, 3, 0) + cam_offset, 1));
                        kill_sequence.AppendCallback( () => {splat.Play();});
                        kill_sequence.Append(people_to_kill[i].transform.DOMoveY(0, 0.5f));
                        kill_sequence.AppendCallback(
                                () => 
                                {
                                    splat_sprite.SetActive(true);
                                    KillPerson(people_to_kill[dumb_i]);
                                    god_happiness = happiness_snapshot + percent * missing_happiness;
                                }
                                );
                        kill_sequence.AppendInterval(0.3f);
                        kill_sequence.AppendCallback(
                                () => 
                                {
                                    splat_sprite.SetActive(false);
                                });

                    }
                    
                    //seriously??
                    kill_sequence.AppendInterval(0.1f);
                    kill_sequence.AppendCallback(
                            () => 
                            {
                                people_to_kill.Clear();
                                current_state = PLAY_STATE.NORMAL;
                            });

                    kill_sequence.Append(happy_music.DOFade(1, 2));
                    kill_sequence.Append(angry_music.DOFade(0, 2));

                    man_scream.Play();
                    village_screams.Play();

                    people_chosen = false;
                }

            } return;

            case PLAY_STATE.PLACING_BUILDING:
            {

                if ( Input.GetMouseButtonDown(1) )
                {
                    placing_object.SetActive(false);
                    current_state = PLAY_STATE.NORMAL;
                    break;
                }

                Vector3 mouse_pos = Input.mousePosition;
                Ray r = Camera.main.ScreenPointToRay(mouse_pos);

                Plane ground_plane = new Plane(Vector3.up, 0);

                float dist;
                if ( ground_plane.Raycast(r, out dist) )
                {
                    Vector3 dest_point = r.GetPoint(dist);
                    dest_point.x = Mathf.Round(dest_point.x/3)*3;
                    dest_point.z = Mathf.Round(dest_point.z/3)*3;

                    placing_object.transform.position = dest_point;

                    if ( Input.GetMouseButtonDown(0) )
                    {
                        bool other_building = false;
                        for ( int i = 0 ; i < buildings.Count; ++i )
                        {
                            if ( buildings[i].transform.position == dest_point )
                            {
                                other_building = true;
                                break;
                            }
                        }

                        if ( !other_building )
                        {
                            place_building.Play();
                            placing_object.SetActive(false);
                            GameObject new_building = (GameObject)Instantiate(hot_prefab, 
                                    dest_point, Quaternion.identity);
                            hot_prefab = null;
                            current_state = PLAY_STATE.NORMAL;

                            Building building_comp = new_building.GetComponent<Building>();
                            if (building_comp != null)
                            {
                                building_comp.type = placing_type;

                                Job new_job = new Job();
                                new_job.goal_point = dest_point;
                                new_job.job_building = building_comp;
                                building_comp.related_job = new_job;

                                switch ( placing_type )
                                {
                                    case BUILDING_TYPE.FARM:
                                        new_job.job_type = JOB_TYPE.BUILD_FARM;
                                        total_money -= farm_cost;
                                        break;
                                    case BUILDING_TYPE.HOUSE:
                                        new_job.job_type = JOB_TYPE.BUILD_HOUSE;
                                        total_money -= house_cost;
                                        break;
                                    case BUILDING_TYPE.SHOP:
                                        new_job.job_type = JOB_TYPE.BUILD_SHOP;
                                        total_money -= shop_cost;
                                        break;
                                }

                                new_job.job_timer = 15;
                                new_job.max_people = 4;
                                new_job.assigned_people = new Person[4];
                                current_jobs.Add(new_job);
                            }
                        }
                    }
                }
            } break;
        }

        //manage jobs
        for ( int i = 0 ; i < current_jobs.Count ; ++i )
        {
            Job job = current_jobs[i];

            if ( job.job_timer < 0 )
            {
                for ( int j = 0 ; j < job.assigned_count ; ++j )
                {
                    job.assigned_people[j].current_job = null;
                    job.assigned_people[j].wander_position = job.assigned_people[j].transform.position;
                }

                //TODO(aidan): perform job completion here
                switch ( job.job_type )
                {
                    case JOB_TYPE.BUILD_FARM:
                    {
                        Destroy(job.job_building.gameObject);
                        GameObject new_building = 
                            (GameObject)Instantiate(farm_prefab, job.goal_point, Quaternion.identity);
                        Building b = new_building.GetComponent<Building>(); 

                        Job new_job = new Job();
                        new_job.goal_point = job.goal_point;
                        new_job.job_building = b;
                        new_job.job_type = JOB_TYPE.TEND_FARM;
                        new_job.job_timer = 1;
                        new_job.max_people = 4;
                        new_job.assigned_people = new Person[4];
                        b.related_job = new_job;
                        current_jobs.Add(new_job);

                    } break;
                    case JOB_TYPE.BUILD_SHOP:
                    {
                        Destroy(job.job_building.gameObject);
                        GameObject new_building = 
                            (GameObject)Instantiate(shop_prefab, job.goal_point, Quaternion.identity);

                        Building b = new_building.GetComponent<Building>(); 

                        Job new_job = new Job();
                        new_job.goal_point = job.goal_point;
                        new_job.job_building = b;
                        new_job.job_type = JOB_TYPE.TEND_SHOP;
                        new_job.job_timer = 1;
                        new_job.max_people = 4;
                        new_job.assigned_people = new Person[4];
                        b.related_job = new_job;
                        current_jobs.Add(new_job);

                    } break;
                    case JOB_TYPE.BUILD_HOUSE:
                    {
                        Destroy(job.job_building.gameObject);
                        Instantiate(house_prefab, job.goal_point, Quaternion.identity);
                    } break;
                    case JOB_TYPE.UPGRADE:
                    {
                        Destroy(job.job_building.gameObject);
                        GameObject building = 
                            (GameObject)Instantiate(job.finished_building.gameObject, 
                                    job.goal_point, Quaternion.identity);
                        Building b = building.GetComponent<Building>();

                        if ( job.finished_building.type != BUILDING_TYPE.HOUSE )
                        {
                            Job new_job = new Job();
                            new_job.goal_point = job.goal_point;
                            new_job.job_building = b;
                            new_job.job_timer = 1;

                            switch ( job.finished_building.type )
                            {
                                case BUILDING_TYPE.FARM:
                                    new_job.job_type = JOB_TYPE.TEND_FARM;
                                    break;
                                case BUILDING_TYPE.SHOP:
                                    new_job.job_type = JOB_TYPE.TEND_SHOP;
                                    break;
                            }

                            new_job.max_people = 4;
                            new_job.assigned_people = new Person[4];
                            b.related_job = new_job;
                            current_jobs.Add(new_job);
                        }

                    } break;
                    case JOB_TYPE.DEMOLISH:
                    {
                        Destroy(job.job_building.gameObject);
                    } break;
                }

                current_jobs.Remove(job);
                --i;
                continue;
            }

            if ( job.max_people > job.assigned_count )
            {
                for ( int j = 0 ; j < people.Count ; ++j )
                {
                    Person p = people[j];
                    if ( p.current_job == null ) 
                    {
                        if ( CorrectWorkTypeForJob(job.job_type, p.work_type ) )
                        {
                            p.current_job = job;
                            job.assigned_people[job.assigned_count++] = p;
                            break;
                        }
                    }
                }
            }
        }

        //update people
        for ( int i = 0 ; i < people.Count ; ++i )
        {
            Person p = people[i];

            if ( p.current_job == null )
            { 
                if ( p.WalkToPoint(p.wander_position, 0.5f) ) 
                {
                    Vector3 new_dir = (Vector3)Random.insideUnitCircle;
                    new_dir.z = new_dir.y;
                    new_dir.y = 0;

                    Vector3 new_wander_pos = p.transform.position + (Vector3)new_dir.normalized * 3;

                    if (new_wander_pos.x < -30 )
                    {
                        new_wander_pos.x = -30;
                    }
                    if (  new_wander_pos.x > 30 )
                    {
                        new_wander_pos.x = 30;
                    }
                    if (new_wander_pos.z < -30 )
                    {
                        new_wander_pos.z = -30;
                    }
                    if (  new_wander_pos.z > 30 )
                    {
                        new_wander_pos.z = 30;
                    }

                    p.wander_position = new_wander_pos;
                }
            }
            else
            {
                if ( p.WalkToPoint(p.current_job.goal_point, 0.5f) )
                {
                    float time_delta =  p.skill * Time.deltaTime;
                    if ( p.current_job.job_building.level > 0 )
                        time_delta *= p.current_job.job_building.level;
                    
                    p.current_job.job_timer -= time_delta;

                    switch ( p.current_job.job_type )
                    {
                        case JOB_TYPE.TEND_FARM:
                        {
                            if ( p.current_job.job_timer < 0 )
                            {
                                p.current_job.job_timer += food_generation_timer;

                                Job j = p.current_job;
                                for (int k = 0 ; k < j.assigned_count; ++k )
                                {
                                    total_food += j.assigned_people[k].skill * 3;
                                }
                            }
                        } break;
                        case JOB_TYPE.TEND_SHOP:
                        {
                            if ( p.current_job.job_timer < 0 )
                            {
                                p.current_job.job_timer += money_generation_timer;

                                Job j = p.current_job;
                                for (int k = 0 ; k < j.assigned_count; ++k )
                                {
                                    total_money += j.assigned_people[k].skill;
                                }
                            }
                        } break;
                        case JOB_TYPE.BUILD_FARM:
                        {
                            if ( construction.isPlaying == false ) construction.Play();
                        } break;
                        case JOB_TYPE.BUILD_SHOP:
                        {
                            if ( construction.isPlaying == false ) construction.Play();
                        } break;
                        case JOB_TYPE.BUILD_HOUSE:
                        {
                            if ( construction.isPlaying == false ) construction.Play();
                        } break;
                        case JOB_TYPE.UPGRADE:
                        {
                            if ( construction.isPlaying == false ) construction.Play();
                        } break;
                    }
                }
            }
        }
	}

    void KillPerson(Person person)
    {
        if ( person.current_job != null )
        {
            Job j = person.current_job;
            for ( int i = 0 ; i < j.assigned_count ; ++i )
            {
                if ( j.assigned_people[i] == person )
                {
                    j.assigned_people[i] = j.assigned_people[--j.assigned_count];
                    break;
                }
            }
        }

        person.current_job = null;
        Destroy(person.name_tag.gameObject);
        Destroy(person.gameObject);
    }


    public void PlaceHouse()
    {
        if ( current_state == PLAY_STATE.BUYING_VILAGER ) 
        {
            buy_buttons.transform.DOScale(0, 1);
            upgrade_button.transform.DOScale(0, 1);
            current_state = PLAY_STATE.NORMAL;
        }

        if ( current_state == PLAY_STATE.NORMAL) 
        {
            if ( total_money >= house_cost )
            {
                current_state = PLAY_STATE.PLACING_BUILDING;
                hot_prefab = construction_prefab;
                placing_type = BUILDING_TYPE.HOUSE;
                placing_object.SetActive(true);
            }
        }
    }

    public void PlaceShop()
    {
        if ( current_state == PLAY_STATE.BUYING_VILAGER ) 
        {
            buy_buttons.transform.DOScale(0, 1);
            upgrade_button.transform.DOScale(0, 1);
            current_state = PLAY_STATE.NORMAL;
        }
        if ( current_state == PLAY_STATE.NORMAL) // || Input.GetKeyDown(KeyCode.C)) )
        {
            if ( total_money >= shop_cost )
            {
                current_state = PLAY_STATE.PLACING_BUILDING;
                hot_prefab = construction_prefab;
                placing_type = BUILDING_TYPE.SHOP;
                placing_object.SetActive(true);
            }
        }
    }

    public void PlaceFarm()
    {
        if ( current_state == PLAY_STATE.BUYING_VILAGER ) 
        {
            buy_buttons.transform.DOScale(0, 1);
            upgrade_button.transform.DOScale(0, 1);
            current_state = PLAY_STATE.NORMAL;
        }
        if ( current_state == PLAY_STATE.NORMAL ) //|| Input.GetKeyDown(KeyCode.X)) )
        {
            if ( total_money >= farm_cost )
            {
                current_state = PLAY_STATE.PLACING_BUILDING;
                hot_prefab = construction_prefab;
                placing_type = BUILDING_TYPE.FARM;
                placing_object.SetActive(true);
            }
        }
    }

    void CreatePerson(int cost, GameObject prefab, WORK_TYPE work_type)
    {
        int free_people = GetFreeHeadCount();
        if ( total_food >= cost && free_people > 0)
        {
            total_food -= cost;

            GameObject new_person = (GameObject)Instantiate(prefab, 
                    buy_house.transform.position, Quaternion.identity);
            Person p = new_person.GetComponent<Person>();

            p.work_type = work_type;
        } 
    }

    public void BuyBuilder()
    {
        if ( current_state == PLAY_STATE.BUYING_VILAGER ) 
            CreatePerson(5, builder_prefab, WORK_TYPE.BUILDER);
    }

    public void BuyFarmer()
    {
        if ( current_state == PLAY_STATE.BUYING_VILAGER ) 
            CreatePerson(3, farmer_prefab, WORK_TYPE.FARMER);
    }
    public void BuyMerchant()
    {
        if ( current_state == PLAY_STATE.BUYING_VILAGER ) 
            CreatePerson(10, merchant_prefab, WORK_TYPE.SHOPKEEPER);
    }

    bool CorrectWorkTypeForJob(JOB_TYPE job_type, WORK_TYPE work_type )
    {
        bool result = false;
        switch ( job_type )
        {
            case JOB_TYPE.TEND_FARM:
            {
                if ( work_type == WORK_TYPE.FARMER ) result = true;
            } break;
            case JOB_TYPE.TEND_SHOP:
            {
                if ( work_type == WORK_TYPE.SHOPKEEPER ) result = true;
            } break;
            case JOB_TYPE.BUILD_FARM:
            {
                if ( work_type == WORK_TYPE.BUILDER ) result = true;
            } break;
            case JOB_TYPE.BUILD_SHOP:
            {
                if ( work_type == WORK_TYPE.BUILDER ) result = true;
            } break;
            case JOB_TYPE.BUILD_HOUSE:
            {
                if ( work_type == WORK_TYPE.BUILDER ) result = true;
            } break;
            case JOB_TYPE.UPGRADE:
            {
                if ( work_type == WORK_TYPE.BUILDER ) result = true;
            } break;
            case JOB_TYPE.WITNESS_RITUAL:
            {
                result = true;
            } break;
            case JOB_TYPE.DEMOLISH:
            {
                if ( work_type == WORK_TYPE.FARMER ) result = true;
            } break;
        }

        return result;
    }

    public void StartUpgrade()
    {
        if ( buy_house.next_level != null && total_money >= buy_house.upgrade_cost )
        {
            buy_buttons.transform.DOScale(0, 1f);
            upgrade_button.transform.DOScale(0, 1f);

            total_money -= buy_house.upgrade_cost;

            Job j = buy_house.related_job;
            if ( j != null )
            {
                for ( int i = 0 ; i < j.assigned_count ; ++i )
                {
                    j.assigned_people[i].current_job = null;
                }
                current_jobs.Remove(j);
            }

            Building b = 
                ((GameObject)Instantiate(construction_prefab, 
                    buy_house.transform.position, 
                    Quaternion.identity)).GetComponent<Building>();

            Job upgrade_job = new Job();
            upgrade_job.goal_point = buy_house.transform.position;
            upgrade_job.job_building = b;
            upgrade_job.job_type = JOB_TYPE.UPGRADE;
            upgrade_job.finished_building = buy_house.next_level;
            upgrade_job.job_timer = 15;
            upgrade_job.max_people = 4;
            upgrade_job.assigned_people = new Person[4];
            b.related_job = upgrade_job;
            current_jobs.Add(upgrade_job);

            Destroy(buy_house.gameObject);
            buy_house = null;
        }
    }

    public void DestroyBuilding(Building building)
    {
        if ( building.related_job != null )
        {
            for ( int i = 0 ; i < building.related_job.assigned_count ; ++i )
            {
                building.related_job.assigned_people[i].current_job = null;
            }
            current_jobs.Remove(building.related_job);
        }
        Destroy(building.gameObject);
    }

    public List<Person> people_to_kill = new List<Person>();

    public void Sacrifice()
    {
        for ( int i = 0 ; i < sacrifice_entries.Length ; ++i )
        {
            Transform toggle_obj = sacrifice_entries[i].transform.FindChild("6");
            Toggle toggle = toggle_obj.GetComponent<Toggle>();

            if ( toggle != null )
            {
                if ( toggle.isOn )
                {
                    people_to_kill.Add(people[i]);
                }
            }
            Destroy(sacrifice_entries[i].gameObject);
        }

        sacrifice_panel.SetActive(false);
        people_chosen = true;
    }
}

