import grpc
import minecraft_pb2_grpc
from minecraft_pb2 import *
from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
from utils_coordinates import Coordinates as coor
import time

class TestAPISimple: 
    
    def __init__(self, client: minecraft_pb2_grpc.MinecraftServiceStub, x=0, y=6, z=0):
        self.client = client
        self.x=x
        self.y=y
        self.z=z
    
    def test_fill_cube(self):
        self.client.fillCube(FillCubeRequest( 
            cube=Cube(
                min=Point(x=self.x-2, y=self.y-3, z=self.z-1),
                max=Point(x=self.x+2, y=self.y-1, z=self.z+1)
            ),
            type=STONE
        ))
        self.client.fillCube(FillCubeRequest( 
            cube=Cube(
                min=Point(x=self.x-2, y=self.y, z=self.z-1),
                max=Point(x=self.x+2, y=self.y, z=self.z+1)
            ),
            type=AIR
        ))
        
    def test_fill_cube_list(self):
        self.client.fillCubeList(FillCubeRequests(fill_cube_requests=[
            FillCubeRequest( 
                cube=Cube(
                    min=Point(x=self.x-2, y=self.y-3, z=self.z-1),
                    max=Point(x=self.x+2, y=self.y-2, z=self.z+1)
                ),
                type=AIR),
            FillCubeRequest( 
                cube=Cube(
                    min=Point(x=self.x-2, y=self.y-3, z=self.z-1),
                    max=Point(x=self.x+2, y=self.y-2, z=self.z+1)
                ),
                type=DEEPSLATE),
            ])
        )
    
    def test_spawn_blocks(self):
        self.client.spawnBlocks(Blocks(blocks=[  
            Block(position=Point(x=self.x+2, y=self.y, z=self.z), type=REDSTONE_WIRE, orientation=EAST),
            Block(position=Point(x=self.x+1, y=self.y, z=self.z), type=REDSTONE_LAMP, orientation=NORTH),
            Block(position=Point(x=self.x, y=self.y, z=self.z), type=REPEATER, orientation=WEST),
            Block(position=Point(x=self.x-1, y=self.y, z=self.z), type=REDSTONE_WIRE, orientation=EAST),
        ]))
        time.sleep(0.5)
        self.client.spawnBlocks(Blocks(blocks=[  
            Block(position=Point(x=self.x-2, y=self.y, z=self.z), type=REDSTONE_BLOCK, orientation=UP),
        ]))
        time.sleep(0.5)
    
    def test_read_cube(self):
        blocks = self.client.readCube(Cube(
                min=Point(x=self.x-2, y=self.y, z=self.z-1),
                max=Point(x=self.x+2, y=self.y, z=self.z+1)
        ))
        for block in blocks.blocks:
            print(f"Position={coor.from_point(block.position)}\tType={BlockType.keys()[block.type]}\tPower={block.power}\tIs_Powered={block.is_powered}")
        print()
    
    def test_read_cube_list(self):
        blocks_list = self.client.readCubeList(Cubes(cubes=[
            Cube(min=Point(x=self.x-2, y=self.y, z=self.z-1), max=Point(x=self.x+2, y=self.y, z=self.z-1)),
            Cube(min=Point(x=self.x-2, y=self.y, z=self.z), max=Point(x=self.x+2, y=self.y, z=self.z)),
            Cube(min=Point(x=self.x-2, y=self.y, z=self.z+1), max=Point(x=self.x+2, y=self.y, z=self.z+1)),
        ]))
        
        for i,blocks in enumerate(blocks_list.blocks_infos):
            print(f"Request: {i}")
            for block in blocks.blocks:
                print(f"Position={coor.from_point(block.position)}\tType={BlockType.keys()[block.type]}\tPower={block.power}\tIs_Powered={block.is_powered}")
        print()
    
    def test_tag_block_types(self):
        blocktypes = [
            OAK_LOG,
            ACACIA_PLANKS,
            STONE,
            BLUE_WOOL,
            GRAY_CONCRETE,
            COMPARATOR,
            CREEPER_HEAD,
        ]
        blocktags = self.client.tagBlockTypes(BlockTypes(block_types=blocktypes))
        for (blocktag, type) in zip(blocktags.block_tags, blocktypes):
            print("Type = {}; {}".format(BlockType.keys()[type],str(blocktag.tag).replace('\n','')))
    
    def test_sign_with_text(self):
        self.client.signsWithText(SignDescriptors(sign_descriptors=[
            SignDescriptor(
                block=Block(position=Point(x=self.x, y=self.y, z=self.z-1), type=OAK_SIGN, orientation=NORTH),
                text="Super awsome simple_test-text."
            ),
            SignDescriptor(
                block=Block(position=Point(x=self.x, y=self.y, z=self.z+1), type=BIRCH_HANGING_SIGN, orientation=SOUTH),
                text="VeryLongTextThatNeedsToBeDivided"
            )
        ]))
    
    def test_send_message(self):
        self.client.sendMessage(Message(
            text="Simple test message to everyone"
        ))
    
    def test_read_response(self):
        message = self.client.readResponse(google_dot_protobuf_dot_empty__pb2.Empty())
        print(f"Message: {message.text}")
    
    def call_all_simple_tests(self):
        self.test_fill_cube()
        self.test_fill_cube_list()
        self.test_spawn_blocks()
        self.test_read_cube()
        self.test_read_cube_list()
        self.test_tag_block_types()
        self.test_sign_with_text()
        self.test_send_message()
        self.test_read_response()
    
    @staticmethod 
    def call_all_simple_tests_default(client: minecraft_pb2_grpc.MinecraftServiceStub):
        s = TestAPISimple(client)
        s.call_all_simple_tests()

if __name__ == "__main__":
    channel = grpc.insecure_channel('localhost:5001')
    client = minecraft_pb2_grpc.MinecraftServiceStub(channel)
    TestAPISimple.call_all_simple_tests_default(client)     
