package ru.cdmlex.jtest.model;

import static ru.cdmlex.jtest.Constants.*;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.ArrayList;
import java.awt.*;
import ru.cdmlex.jtest.Materials;

public class Map {
	private int tile[][] = new int[WORLD_WIDTH][WORLD_HEIGHT];
	private List<DrawTile> map_0 = new ArrayList<DrawTile>();
	private List<DrawTile> map_1 = new ArrayList<DrawTile>();
	private int door1;
	private int door2;
	private int door3;
	int c_sz_door1 = 16;
	int c_sz_door2 = 8;
	int ANIM1 = 0;
	int ANIM2s = 0;
	int ANIM2 = 0;
	int ANIM3 = 0;
	int mag_live;
	int mag_timer;
	public Map(String filename) {
		for (int y = 0; y < WORLD_HEIGHT; y++)
		for (int x = 0; x < WORLD_WIDTH; x++) 
			tile[x][y] = -1;
		
		door1 = 0;
		door2 = 0;
		door3 = 0;
		mag_live = 0;
		mag_timer = 0;
		try {
			List<String> lines = Files.readAllLines(Paths.get(filename), StandardCharsets.UTF_8);
			for (int y = 0; y < lines.size(); y++) 
			if (y < 18) {
				String temp = lines.get(y);
				int length = temp.length();
				for (int x = 0; x < length; x++) 
				switch(temp.charAt(x)) {
					case ' ': tile[x][y] = -1; break;
					case '.': tile[x][y] =  -2; break;
					case 'E': tile[x][y] = 0; break;
					case 'L': tile[x][y] = 1; break;
					case 'P': tile[x][y] = 2; break;
					case '1': tile[x][y] = 3; door1 = c_sz_door1; break;
					case '2': tile[x][y] = 4; door2 = c_sz_door2; break;
					case '3': tile[x][y] = 5; door3 = c_sz_door2; break;
					case '#': tile[x][y] = 6; break;
					case 'I': tile[x][y] =  8; break;
					case '4': tile[x][y] = 10; break;
					case '5': tile[x][y] = 11; break;					
					case 'S': tile[x][y] = 12; break;
					case 'D': tile[x][y] = 14; door2 = c_sz_door2; break;
					case 'N': tile[x][y] = 16; door1 = c_sz_door1; mag_live = 5; break;
				}
			}
		}
		catch(IOException e) {
		}
		for (int y = 1; y < WORLD_HEIGHT; y++)
		for (int x = 0; x < WORLD_WIDTH; x++) {
			if ((tile[x][y] == 6) & (tile[x][y-1] == 6))
				tile[x][y-1] = 7;
		}
		placeApple(1, -2);
		update();
	}
	public void update() {
		map_0.clear();
		map_1.clear();
		ANIM1++;
		if (ANIM1 > 5)
			ANIM1 = 0;
			
		ANIM2s+=45;	
		if (ANIM2s > 360)
			ANIM2s -= 360;
		
		ANIM2 = (int)(2*Math.cos(Math.toRadians(ANIM2s)));
	
		ANIM3++;
		if (ANIM3 > 6)
			ANIM3 = 0;
			
		if (mag_live > 0) {
			mag_timer++;
			if (mag_timer == 10) {
				placeApple(-3, -1);
				placeApple(-3, -1);
				placeApple(-3, -1);
			}
			else
			if (mag_timer > 36) {
				mag_timer = - 50;
			}
		
		}
		
		for (int y = 0; y < WORLD_HEIGHT; y++)
		for (int x = 0; x < WORLD_WIDTH; x++) {
			int t = tile[x][y];
			if (!((t == 10)&(door2<2)) & !((t == 11)&(door3<2))) {

				if (t > 0) {
					int dy = CELL_SIZE;
					
					if (t < 6)
						dy = dy + 3 - ANIM2;
					if (t > 11)
						t+= (int)ANIM1/3;
					
					if (t < 6)
					  map_0.add(new DrawTile(x * CELL_SIZE, y * CELL_SIZE, 3, 0));
					map_1.add(new DrawTile(x * CELL_SIZE, y * CELL_SIZE-dy, t, 1));
					
				}
				else
				if (t == 0)
					map_0.add(new DrawTile(x * CELL_SIZE, y * CELL_SIZE-CELL_SIZE+2, t, 1));
				else
				if(t== - 2)
					map_0.add(new DrawTile(x * CELL_SIZE, y * CELL_SIZE, 0, 0));
				else
				if (t== - 3) {
					if (ANIM3 < 4)
						map_0.add(new DrawTile(x * CELL_SIZE, y * CELL_SIZE+2, 2, 0));
					if ((mag_timer > 20) & (ANIM3 < 6))
						map_1.add(new DrawTile(x * CELL_SIZE, y * CELL_SIZE-CELL_SIZE, 2, 0));
					if (mag_timer == 36)
						tile[x][y] = 12;
				}
			}
		}
		if ((door1 > 0) & (door1 < c_sz_door1)) door1--;
		if ((door2 > 0) & (door2 < c_sz_door2)) door2--;
		if ((door3 > 0) & (door3 < c_sz_door2)) door3--;
		
	}
	public void draw0(Graphics2D g, Materials materials) {
		for (DrawTile d : map_0) {
			Materials.s_tl[d.g].draw_a(g, d.x, d.y,d.t);
			if ((d.g == 1) & (d.t == 0) & (door1 > 0))
			  Materials.s_tl[1].draw_a_sl(g, d.x, d.y, 9, 8, door1);
		
		}
	}
	
	public void draw1(Graphics2D g, Materials materials) {
		for (DrawTile d : map_1) {
			if ((d.g==0)&(d.t == 2)) 
			 Materials.s_tl[1].draw_a_sl2(g, d.x, d.y, 12, mag_timer-20);
			else
			if ((d.g==1)&(d.t == 10) & (door2 > 0))
			  Materials.s_tl[d.g].draw_a_sl(g, d.x, d.y, d.t, door2, 16);
			else
			if ((d.g==1)&(d.t == 11) & (door3 > 0))
			  Materials.s_tl[d.g].draw_a_sl(g, d.x, d.y, d.t, door3, 16);			
			else
			Materials.s_tl[d.g].draw_a(g, d.x, d.y, d.t);
		}
	}
	
	public boolean freeway(int x, int y) {
            if (x < 0)
				x = WORLD_WIDTH;
            else
            if (x >= WORLD_WIDTH) 
				x = 0;
            
            if (y < 0)
				y = WORLD_HEIGHT;
            else
            if (y >= WORLD_HEIGHT) 
				y = 0;
				
	
		if ((x >= 0) & (x < WORLD_WIDTH) & (y >= 0) & (y < WORLD_HEIGHT))
			return 
			  !( (tile[x][y] > 5) & (tile[x][y] < 9) )
			&!( (tile[x][y] == 10) & (door2 > 0) ) 
			&!( (tile[x][y] == 11) & (door3 > 0) );
		else
			return true;
	}
	
	public boolean bullet_col(int x, int y) {
	
		if ((x >= 0) & (x < WORLD_WIDTH) & (y >= 0) & (y < WORLD_HEIGHT)) {
			if (freeway(x, y)) {
				int t = tile[x][y];
				if (t > 11) {
					switch(t) {
						case 12:
							tile[x][y] = -1;
						break;
						case 14:
							tile[x][y] = 4;
						break;
						case 16:
							mag_live--;
							if (mag_live < 1)
							tile[x][y] = 3;
						break;					
					}
					return true;
				}
				return false;
			}
			else
			return true;
		}
			return true;
	}
	
    public void placeApple(int tp, int whr) {
		int t = 100;
        int x = (int)(Math.random() * WORLD_WIDTH);
        int y = (int)(Math.random() * WORLD_HEIGHT);
        while ((tile[x][y]!=whr) | (t > 0) /*!isCellEmpty(x, y)*/) {
			x = (int)(Math.random() * WORLD_WIDTH);
			y = (int)(Math.random() * WORLD_HEIGHT);
			t--;
        }
        tile[x][y] = tp;
    }

	public int action(int x, int y) {
		if ((x >= 0) & (x < WORLD_WIDTH) & (y >= 0) & (y < WORLD_HEIGHT)) {
			switch(tile[x][y]) {
				case 0:
					if (door1 > 0)
						return -1;
					break;
				case 1:
					placeApple(1, -2);
					tile[x][y] =-2;
					return (1);
				case 2:
					tile[x][y] =-2;
					return (2);
				case 3:
					tile[x][y] = -1;
					door1--;
					break;
				case 4:
					tile[x][y] = -1;
					door2--;
					break;
				case 5:
					tile[x][y] = -1;
					door3--;
					break;
			}
			return tile[x][y];
		}
		else
			return -1;
	}
}