package de.samdev.colorrunner.game.world.map.provider;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Rectangle;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import de.samdev.colorrunner.game.renderer.AbstractGameRenderer;
import de.samdev.colorrunner.game.world.CRGameWorld;
import de.samdev.colorrunner.game.world.entities.CRGameEntity;
import de.samdev.colorrunner.game.world.entities.gameentities.floor.FloorTileEntity;
import de.samdev.colorrunner.game.world.map.CRMapStorage;
import de.samdev.colorrunner.game.world.map.CRTiledMap;
import de.samdev.colorrunner.game.world.map.MapSection;

public class EndlessMapProvider extends MapProvider {
    private final Random random;

    public List<MapSection> sections;
    private int mapRightBoundary = 0;

    public EndlessMapProvider(long seed) {
        random = new Random(seed);
    }

    @Override
    public void init(CRGameWorld world) {
        sections = new ArrayList<MapSection>();
        mapRightBoundary = appendMap(world, CRMapStorage.map_start, 0);
    }

    @Override
    public boolean isNextEndlessMenu(){
        return true;
    }

    @Override
    public TriggerType getTrigger(int x, int y) {

        for(int i = sections.size()-1; i >= 0; i--)
        {
            int start = sections.get(i).start;
            int end = sections.get(i).end;

            if(start <= x && end > x){
                if (y < 0) return TriggerType.NOTHING;
                if (y >= sections.get(i).crTiledMap.getHeight()) return TriggerType.NOTHING;

                if( sections.get(i).crTiledMap.interaktionen[x - start][y] == CRTiledMap.GID_INTER_UP)
                   return TriggerType.RUNTOP;
                else if( sections.get(i).crTiledMap.interaktionen[x - start][y] == CRTiledMap.GID_INTER_DOWN)
                   return  TriggerType.RUNTOP;
                else if( sections.get(i).crTiledMap.interaktionen[x - start][y] == CRTiledMap.GID_INTER_RIGHT)
                   return  TriggerType.FLY;
                else if( sections.get(i).crTiledMap.interaktionen[x - start][y] == CRTiledMap.GID_INTER_MID)
                    return TriggerType.GRAVITY;
                else if( sections.get(i).crTiledMap.interaktionen[x - start][y] == CRTiledMap.GID_INTER_END)
                    return TriggerType.END;
                else if(sections.get(i).crTiledMap.interaktionen[x - start][y] ==  0)
                    return TriggerType.NOTHING;
                else {
                    Gdx.app.error("MapProvider", "Unknown trigger: " + sections.get(i).crTiledMap.interaktionen[x][y]);
                    return TriggerType.NOTHING;
                }
            }
        }
        return TriggerType.NOTHING;
    }

    @Override
    public MapProvider createNew() {
        EndlessMapProvider endlessMapProvider = new EndlessMapProvider(System.currentTimeMillis());
        return endlessMapProvider;
    }

    @Override
    public void update(CRGameWorld world, Rectangle player)
    {
        while (player.x + AbstractGameRenderer.MAX_GAME_WIDTH*2 > mapRightBoundary * FloorTileEntity.FLOORTILE_WIDTH) {
            float width = appendMap(world, CRMapStorage.getMap(random), mapRightBoundary);
            mapRightBoundary += width;
        }
    }

    private int appendMap(CRGameWorld world, CRTiledMap map, int posX) {
        int height = map.getHeight();
        int width = map.getWidth();

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                float px = posX * FloorTileEntity.FLOORTILE_WIDTH + x * FloorTileEntity.FLOORTILE_WIDTH;
                float py = y * FloorTileEntity.FLOORTILE_WIDTH;

                CRGameEntity e = CRTiledMap.CreateTile(world, map.getGID(x, y), px, py);
                if (e != null) world.addEntity(e);
            }
        }

        sections.add(new MapSection(posX, width, map.name, map));

        return width;
    }

    public MapSection getCurrentSection(Rectangle player) {
        for (MapSection sec : sections) {
            if (sec.start <= player.x && sec.end >= player.x)
                return sec;
        }

        return new MapSection(0, 0, "NULL", null);
    }
}
