# Lair Configuration DSL Case Study (Python 3)
# Method Chaining with Expression: Configuration Builder (builder14)
# H. Conrad Cunningham

# Developed for CSci 658, Software Language Engineering, Spring 2018

#234567890123456789012345678901234567890123456789012345678901234567890

# 2018-02-27: (V1) adapted from M. Fowler's Ruby version build14.rb
#             and my Lua version build14.lua

# Import Semantic Model for Configuration
from model import *

def load_dsl(dsl_file):
    with open(dsl_file, 'r') as f:
        dsl_str = f.read()
    result = eval(dsl_str)
    return result.configuration()

# Unlike Ruby code must start DSL script with instance
class ConfigurationBuilder:

    def __init__(self):
        self._subject = Configuration()

    @property
    def subject(self):
        return self._subject

    def item(self,arg):
        result = ItemBuilder(self,arg) 
        self._subject.add_item(result.subject)
        return result

    # Added to Python version
    def configuration(self):
        return self.subject

    def __str__(self):
        return "ComputerBuilder: " + str(self.subject)

class ItemBuilder:

    def __init__(self,parent,arg):
        self._parent = parent
        self._subject = Item(arg)

    @property
    def subject(self):
        return self._subject
    
    @property
    def parent(self):
        return self._parent

    def item(self,arg):
        return self.parent.item(arg)

    def provides(self,arg):
        self.subject.add_provision(arg.subject)
        return self

    def uses(self,arg):
        self.subject.add_usage(arg.subject)
        return self

    def depends_on(self,arg):
        self.subject.add_dependency(
            self.configuration().get_item(arg))
        return self

    def configuration(self):
        return self.parent.configuration()

    def __str__(self):
        return ("ItemBuilder: " + str(self.subject) + "\n" +
                    "with parent: " + str(self.parent))

class Resources:

    @classmethod
    def electricity(cls,power):
        return ElectricityBuilder(power)

    @classmethod
    def acid(cls):
      return AcidBuilder()

class AcidBuilder:

    def __init__(self):
        self._subject = Acid()

    @property
    def subject(self):
        return self._subject
    
    def type(self,arg):
        self.subject.type = arg
        return self

    def grade(self,arg):
        self.subject.grade = arg
        return self

    def __str__(self):
        return "AcidBuilder: " + str(self.subject)

class ElectricityBuilder:

    def __init__(self,arg):
        self._subject = Electricity(arg)

    @property
    def subject(self):
        return self._subject

    def __str__(self):
        return "ElectricityBuilder: " + str(self.subject)

    
