package sokobanevo.levels;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;

/**
 * Class designed for use by SokobanEvo.
 * 
 * Contains functions for manipulation with level, as loading from file or drawing using Slick2D.
 * 
 * @author Payne
 */
public class LevelDraw {
    
    final static Charset ENCODING = StandardCharsets.UTF_8;
    final static String mapFilePath = "assets/schaul.txt";
    final static int TILE_SIZE = 16;
    private final String floorImgFilePath = "assets/textures/floor_16.png";
    private final String boxImgFilePath = "assets/textures/box_16.png";
    private final String sokoImgFilePath = "assets/textures/tpack_16.png";
    private final String holeImgFilePath = "assets/textures/hole_16.png";
    private final String wallImgFilePath = "assets/textures/wall_16.png";
    private final String goalImgFilePath = "assets/textures/goal_16.png";
    private final String visitableImgFilePath = "assets/textures/visitable_16.png";
    private Image floorImg;
    private Image wallImg;
    private Image sokoImg;
    private Image holeImg;
    private Image boxImg;
    private Image goalImg;
    private Image visitableImg;
    
    /**
    * Constructor, textures used are initialized here.
    */
    public LevelDraw() throws SlickException{
        floorImg = new Image(floorImgFilePath);
        wallImg = new Image(boxImgFilePath);
        sokoImg = new Image(sokoImgFilePath);
        holeImg = new Image(holeImgFilePath);
        boxImg = new Image(wallImgFilePath);
        goalImg = new Image(goalImgFilePath);
        visitableImg = new Image(visitableImgFilePath);
    }
    
    /**
    * Function, reads specific map from text file, identified by id.
    * 
    * @param id id of map in file.
    * @return 2D array containing map.
    */
    public ArrayList<char[]> readMapFromFileById(int id) throws IOException{
        ArrayList<char[]> map = new ArrayList<char[]>();
        Path path = Paths.get(mapFilePath);
        System.out.println(path.toString());
        
        try (BufferedReader reader = Files.newBufferedReader(path, ENCODING)){
            String line = null;
            Pattern digitPattern = Pattern.compile("-?\\d+");
            while ((line = reader.readLine()) != null) {
                Matcher matcher = digitPattern.matcher(line);
                matcher.find();
                if(line.length() >= 3 && line.charAt(0) == ';' && line.charAt(1) == ' ' && matcher.group().equals(Integer.toString(id))){
                    line = reader.readLine();
                    int i = 0;
                    line = reader.readLine();
                    while(line != null && line.length() > 0){
                        map.add(i,line.toCharArray());
                        for(int j = 0; j < map.get(i).length; j++){
                            if(map.get(i)[j] == '*'){
                                map.get(i)[j] = ' ';
                            }
                        }
                        i++;
                        line = reader.readLine();
                    }
                }
            }
        }
        
        return map;
    }
    
    /**
    * Function, draws level on screen, using Slick2D.
    * 
    * Function designed to be called from render() function of Slick2D game container.
    * 
    * @param level 2D representation of map to be drawn.
    */
    public void drawLvlAt(int xpos, int ypos, ArrayList<char[]> level){
        for(int i = 0; i < level.size(); i++){
            for(int j = 0; j < level.get(i).length; j++){
                switch(level.get(i)[j]){
                    case '#':
                        wallImg.draw((float)xpos + j*TILE_SIZE, (float)ypos + i*TILE_SIZE);
                        break;
                    case '@':
                        sokoImg.draw((float)xpos + j*TILE_SIZE, (float)ypos + i*TILE_SIZE);
                        break;
                    case '$':
                        boxImg.draw((float)xpos + j*TILE_SIZE, (float)ypos + i*TILE_SIZE);
                        break;
                    case '.':
                        holeImg.draw((float)xpos + j*TILE_SIZE, (float)ypos + i*TILE_SIZE);
                        break;
                    case ' ':
                        floorImg.draw((float)xpos + j*TILE_SIZE, (float)ypos + i*TILE_SIZE);
                        break;
                     case 'x':
                        goalImg.draw((float)xpos + j*TILE_SIZE, (float)ypos + i*TILE_SIZE);
                        break;
                     case 's':
                        sokoImg.draw((float)xpos + j*TILE_SIZE, (float)ypos + i*TILE_SIZE);
                        break;
                     case 'v':
                        visitableImg.draw((float)xpos + j*TILE_SIZE, (float)ypos + i*TILE_SIZE);
                        break;
                }
            }
        }
    }
}
