import random
from typing import Dict, List, Optional, Tuple
from PIL import Image

import carla
import os

import time

RGB_SETTING = [
    [
        [0, 0, 0],
        [255, 255, 255],
        [255, 0, 0],
        [0, 255, 0],
        [0, 0, 255],
        [128, 128, 0],
        [255, 128, 255],
        [128, 255, 128],
        [0, 0, 128],
        [255, 255, 255],
        [128, 128, 0],
        [255, 0, 0],
        [255, 255, 0],
        [0, 0, 0],
    ],

    [
        [255, 255, 255],
        [0, 0, 0],
        [0, 255, 0],
        [255, 0, 0],
        [128, 128, 0],
        [0, 0, 255],
        [128, 255, 128],
        [255, 128, 255],
        [255, 255, 255],
        [0, 0, 128],
        [255, 0, 0],
        [128, 128, 0],
        [0, 0, 0],
        [255, 255, 0],
    ],

    [
        [255, 255, 0],
        [0, 0, 0],
        [128, 128, 0],
        [255, 0, 0],
        [0, 0, 128],
        [255, 255, 255],
        [255, 128, 255],
        [128, 255, 128],
        [0, 0, 255],
        [128, 128, 0],
        [255, 0, 0],
        [0, 255, 0],
        [0, 0, 0],
        [255, 255, 255],
    ],

    [
        [0, 0, 0],
        [255, 255, 255],
        [255, 128, 255],
        [255, 255, 0],
        [0, 0, 255],
        [0, 255, 0],
        [128, 128, 0],
        [255, 0, 0],
        [255, 0, 0],
        [128, 128, 0],
        [0, 0, 128],
        [255, 255, 255],
        [0, 0, 0],
        [128, 255, 128],
    ],
]

TEST_RGB_SETTING = [
    [
        [128, 128, 128],
        [128, 0, 0],
        [0, 0, 255],
        [0, 96, 0],
        [0, 0, 0],
        [0, 0, 0],
        [255, 255, 255],
        [255, 255, 255],
        [204, 102, 0],
        [0, 96, 0],
        [255, 255, 255],
        [0, 0, 128],
        [128, 0, 0],
        [128, 128, 128],
    ],

    [
        [128, 0, 0],
        [128, 128, 128],
        [0, 96, 0],
        [0, 0, 255],
        [255, 255, 255],
        [128, 128, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 96, 0],
        [204, 102, 0],
        [0, 0, 128],
        [255, 255, 255],
        [128, 128, 128],
        [128, 0, 0],
    ],

    [
        [255, 255, 255],
        [0, 0, 255],
        [0, 0, 0],
        [192, 0, 0],
        [204, 102, 0],
        [0, 96, 0],
        [0, 0, 0],
        [96, 0, 96],
        [0, 96, 0],
        [128, 128, 128],
        [0, 96, 0],
        [0, 0, 0],
        [0, 0, 0],
        [255, 255, 255],
    ]
]

def category_texture_change(category, rgb: list, specific_name=None):
    for idx, name in enumerate(texture_list):
        if category in name:
            image = Image.open(os.path.join('carla_env/textures', name))
            height = image.size[1]
            width = image.size[0]

            texture = carla.TextureColor(width, height)
            for x in range(0, width):
                for y in range(0, height):
                    a = 255
                    texture.set(x, y, carla.Color(*rgb, a))

            if specific_name is None:
                specific_name = category

            print(list(filter(lambda k: f'{specific_name}' in k, world.get_names_of_all_objects())))
            name_list = list(filter(lambda k: f'{specific_name}' in k, world.get_names_of_all_objects()))
            for obj_name in name_list:
                world.apply_color_texture_to_object(obj_name, carla.MaterialParameter.Diffuse, texture)
            break


if __name__=='__main__':

    client = carla.Client('115.145.178.250', 10060)
    client.set_timeout(10.0)

    world = client.get_world()

    # rgb_list = [
    #     [0, 0, 0],
    #     [255, 255, 255],  # Block12
    #     [255, 0, 0],  # [255, 0, 0], Block13 = Skyscraper_04
    #     [0, 255, 0],  # Block14
    #     [0, 0, 255],  # Factory
    #     [128, 128, 0],  # [255, 255, 0], Hotel
    #     [255, 128, 255],  # Museum
    #     [128, 255, 128],  # SkyEvo
    #     [0, 0, 128],  # [128, 128, 255], Skyscraper_01
    #     [255, 255, 255],  # [128, 255, 128], Skyscraper_02
    #     [128, 128, 0],  # [255, 128, 128], Skyscraper_03
    #     [255, 0, 0],  # [255, 255, 128], Skyscraper_04
    #     [255, 255, 0],  # [255, 128, 255], Skyscraper_05
    #     [0, 0, 0],  # [255, 255, 128],
    # ]


    rgb_list = TEST_RGB_SETTING[2]

    dir_path = 'carla_env/textures'
    texture_list = os.listdir(dir_path)
    texture_list.sort()

    # f = open('test.txt', 'w')

    # objects = world.get_environment_objects()
    # objects_names = []
    # for object in objects:
    #     # if 'Skyscraper' in str(object.name) or 'Hotel' in str(object.name) or 'Block' in str(object.name):
    #     #     print(object.type, object.name)
    #
    #     if 'Base' in str(object.name):
    #         print(object.type, object.name)
    #
    #     if str(object.type) == "Buildings":
    #         # print(object.type, object.name, object.id)
    #         objects_names.append(str(object.name))
    # objects_names.sort()
    # for object in objects_names:
    #     f.write(f'{object}\n')

    # obj_names = []
    # for idx, name in enumerate(texture_list):
    #     str_name = name.split('.TGA')[0]
    #     new_list = list(map(str, filter(lambda k: f'{str_name}' in k, world.get_names_of_all_objects())))
    #     obj_names.extend(new_list)
    #
    # for idx, name in enumerate(texture_list):
    #     print(name, rgb_list[idx])
    #     image = Image.open(os.path.join(dir_path, name))
    #     height = image.size[1]
    #     width = image.size[0]
    #
    #     r, g, b = rgb_list[idx]
    #
    #     # Instantiate a carla.TextureColor object and populate
    #     # the pixels with data from the modified image
    #     texture = carla.TextureColor(width, height)
    #     for x in range(0, width):
    #         for y in range(0, height):
    #             color = image.getpixel((x, y))
    #             a = 255
    #             texture.set(x, y, carla.Color(r, g, b, a))
    #
    #     # print("finish")
    #     str_name = name.split('.TGA')[0]
    #     print(list(filter(lambda k: f'{str_name}' in k, world.get_names_of_all_objects())))
    #     name_list = list(filter(lambda k: f'{str_name}' in k, world.get_names_of_all_objects()))
    #     # Now apply the texture to the building asset
    #     for obj_name in name_list:
    #         world.apply_color_texture_to_object(obj_name, carla.MaterialParameter.Diffuse, texture)



    # Test setting 1
    # category_texture_change('Apartment04', [102, 0, 204], 'Apartment04_v05')
    # category_texture_change('Apartment04', [102, 0, 204], 'Apartment04_v03')
    # category_texture_change('Apartment04', [102, 0, 204], 'Apartment04_v02')
    # category_texture_change('Apartment04', [102, 0, 204], 'Apartment04_v01')
    # category_texture_change('Block13', [192, 192, 0], 'BP_Block13NY_v04')
    # category_texture_change('Block13', [192, 192, 0], 'BP_Block13NY_v04')
    # category_texture_change('Block13', [192, 192, 0], 'BP_Block13NY_v03')
    # category_texture_change('Skyscraper_01', [96, 0, 96], 'Skyscraper_01_v02')
    # category_texture_change('Skyscraper_01', [96, 0, 96], 'Skyscraper_01_v01')

    # Test setting 2
    # category_texture_change('Apartment04', [96, 0, 96], 'Apartment04_v05')
    # category_texture_change('Apartment04', [96, 0, 96], 'Apartment04_v03')
    # category_texture_change('Apartment04', [96, 0, 96], 'Apartment04_v02')
    # category_texture_change('Apartment04', [96, 0, 96], 'Apartment04_v01')
    # category_texture_change('Block13', [102, 0, 204], 'BP_Block13NY_v04')
    # category_texture_change('Block13', [102, 0, 204], 'BP_Block13NY_v04')
    # category_texture_change('Block13', [102, 0, 204], 'BP_Block13NY_v03')
    # category_texture_change('Skyscraper_01', [192, 192, 0], 'Skyscraper_01_v02')


    # Test setting 3
    category_texture_change('Apartment04', [255, 255, 255])
    category_texture_change('Apartment04', [0, 96, 0], 'Apartment04_v05')
    category_texture_change('Apartment04', [0, 96, 0], 'Apartment04_v03')
    category_texture_change('Apartment04', [0, 96, 0], 'Apartment04_v02')
    category_texture_change('Apartment04', [0, 96, 0], 'Apartment04_v01')
    # category_texture_change('Block13', [192, 192, 0], 'BP_Block13NY_v04')
    # category_texture_change('Block13', [192, 192, 0], 'BP_Block13NY_v04')
    # category_texture_change('Block13', [192, 192, 0], 'BP_Block13NY_v03')
    # category_texture_change('Skyscraper_01', [128, 0, 0], 'Skyscraper_01_v02')
    # category_texture_change('Skyscraper_01', [128, 0, 0], 'Skyscraper_01_v01')