from ..primitives.library import gds_library
from ..primitives.layer import gds_layer
from ..properties.initializer import strong_property_initializer
from ..properties.descriptor import property_descriptor, restricted_property
from ..properties.restrictions import restrict_type
from ..properties.predefined import length_property, string_property
import sys


__all__ = []

#######################################################################
## Basic input module
#######################################################################
class basic_input(strong_property_initializer):
    i_stream = property_descriptor(default = sys.stdin) # add limitation
    def __init__(self, i_stream = sys.stdin, **kwargs):
        super(basic_input, self).__init__(
            i_stream = i_stream,
            **kwargs)

    def read(self, size = None):
        if size == None:
            return self.parse(self.i_stream.read())
        else:
            return self.parse(self.i_stream.read(size))

    def parse(self, item):
        return item

#######################################################################
## Basic GDS input stream
#######################################################################
class basic_gds_input(basic_input):
    scaling = length_property(default = 1.0)
    layer_map = restricted_property(restriction = restrict_type(dict), default = {})
    prefix = string_property(default = "")
    def __init__(self, i_stream = sys.stdin, **kwargs):
        super(basic_gds_input, self).__init__(
            i_stream = i_stream,
            **kwargs)
        self.library = None

    def read(self):
        return self.parse()
        

    def parse(self):
        return self.parse_library()

    def parse_library(self):
        self.library = gds_library("IMPORT")
        self.__parse_library__()
        return self.library

    def map_layer(self, layer_number):
        if layer_number in self.layer_map:
            L = self.layer_map[layer_number]
            if isinstance(L, gds_layer):
                return L
            else:
                return gds_layer(L)
        else:
            return gds_layer(layer_number)

    def make_structure_name(self, name):
        return self.prefix + name

#################################################
## Element Types
#################################################
Type_Boundary = 1
Type_Path = 2
Type_SRef = 3
Type_ARef = 4
Type_Label = 5
Type_Box = 6