/**
* Provides a data service to create base and demo data.
* Beware that most, if not all, base data is referenced by "Id" throughout the program.
* This allows changing the text of the 'name' property to something of the same meaning.
* But be sure to maintain the correct Id during creation, indicated by #1, #2 etc.
*/
class  CreateDataService {

    boolean transactional = false

    def personService
    def taskService
    def dateUtilService
    def appConfigService

/*******************************************
Start of Group methods.
Generally use these methods to create data.
*******************************************/

    /**
    * Always call this at startup to ensure that we have admin access
    * and that the system pseudo person is available.
    */
    def ensureSystemAndAdminAccess() {
        if(!Authority.findByAuthority("ROLE_AppAdmin") ) {
            log.warn "ROLE_AppAdmin not found, calling createAdminAuthority()."
            createAdminAuthority()
        }
        if(!Person.findByloginName("system") ) {
            log.warn "LoginName 'system' not found, calling createSystemPerson()."
            createSystemPerson()
        }
        if(!Person.findByloginName("admin") ) {
            log.warn "LoginName 'admin' not found, calling createAdminPerson()."
            createAdminPerson()
        }
    }

    /**
    * Create the base data required for the application to function.
    */
    def createBaseData() {

        if(appConfigService.exists("baseDataCreated")) {
            log.error "Base data has already been created, will NOT recreate."
            return false
        }

        log.info "Creating base data..."

        // Person and Utils
        createBaseAuthorities()
        createBasePersonGroups()
        createBaseUnitsOfMeasure()
        createBasePeriods()
        createBaseSupplierType()
        createBaseManufacturerType()

        // Tasks
        createBaseTaskGroups()
        createBaseTaskStatus()
        createBaseTaskPriorities()
        createBaseTaskTypes()
        createBaseTaskModificationTypes()
        createBaseEntryTypes()

        // Inventory
        createBaseInventoryTypes()
        createBaseInventoryMovementTypes()
        createBaseMaintenancePolicies()

        // Assets
        createBaseAssetExtenededAttributeTypes()

        // Record that data has been created.
        appConfigService.set("baseDataCreated")
    }

    /**
    * Create demo data for some example sites.
    */
    def createDemoData() {

        if(!appConfigService.exists("baseDataCreated")) {
            log.error "Demo data cannot be created until base data has been created."
            return false
        }

        if(appConfigService.exists("demoDataCreated")) {
            log.error "Demo data has already been created, will NOT recreate."
            return false
        }

        if(appConfigService.exists("demoDataCreationDisabled")) {
            log.error "Demo data creation has been disabled, will NOT create."
            return false
        }

        log.info "Creating demo data..."

        // Person and Utils
        createDemoPersons()
        createDemoSites()
        createDemoDepartments()
        createDemoSuppliers()
        createDemoManufacturers()

        // Tasks
        createDemoTasks()
        createDemoEntries()
        createDemoAssignedGroups()
        createDemoAssignedPersons()
        createDemoTaskRecurringSchedules()

        // Inventory
        createDemoInventoryStores()  /// @todo: Perhaps a 'createQuickStartData' method?
        createDemoInventoryLocations()
        createDemoInventoryGroups() /// @todo: Perhaps a 'createQuickStartData' method?
        createDemoInventoryItems()

        // Assets
        createDemoLifePlan()
        createDemoTaskProcedure()
        createDemoMaintenanceActions()
        createDemoSystemSections()
        createDemoAssetTypes()
        createDemoAssemblies()
        createDemoSubAssemblies()
        createDemoComponentItems()
        createDemoAssets()
        createDemoAssetExtenedAttributes()

        // Record that data has been created.
        appConfigService.set("demoDataCreated")
    }

/******************
Start of Person
*******************/

    def createAdminAuthority() {
        def authInstance

        authInstance = new Authority(description:"Application Admin, not required for daily use! Grants full admin access to the application.",
                                        authority:"ROLE_AppAdmin")
        saveAndTest(authInstance)
    }

    def createBaseAuthorities() {

        def authInstance

        authInstance = new Authority(description:"Business manager, grants full management access.",
                                        authority:"ROLE_Manager")
        saveAndTest(authInstance)

        authInstance = new Authority(description:"Application User, all application users need this base role to allow login.",
                                        authority:"ROLE_AppUser")
        saveAndTest(authInstance)
    }

    void createBasePersonGroups() {
        //TypeOfPersonGroup
        def personGroupTypeInstance
            personGroupTypeInstance = new PersonGroupType(name:"Team")
        saveAndTest(personGroupTypeInstance)
            personGroupTypeInstance = new PersonGroupType(name:"Contractor")
        saveAndTest(personGroupTypeInstance)
            personGroupTypeInstance = new PersonGroupType(name:"ProjectTeam")
        saveAndTest(personGroupTypeInstance)

        //PersonGroup
        def personGroupInstance
            personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(1),
                            name:"Electrical")
        saveAndTest(personGroupInstance)
            personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(1),
                            name:"Mechanical")
        saveAndTest(personGroupInstance)
            personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(1),
                            name:"Production")
        saveAndTest(personGroupInstance)
            personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(2),
                            name:"Kewl AirCon Guys")
        saveAndTest(personGroupInstance)
            personGroupInstance = new PersonGroup(personGroupType:PersonGroupType.get(3),
                            name:"gnuMims")
        saveAndTest(personGroupInstance)
    }

    def createSystemPerson() {
        //Person
        def passClearText = "pass"
        def passwordEncoded = personService.encodePassword(passClearText)
        def personInstance

        //Person #1
        personInstance = new Person(loginName:"system",
                                    firstName:"gnuMims",
                                    lastName:"System",
                                    description:'''This is a pseudo person that the application uses to insert data. DO NOT
                                                        assign login authorities or change the details of this person.''',
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"system@example.com")
        saveAndTest(personInstance)
    }

    def createAdminPerson() {
        //Person
        def passClearText = "pass"
        def passwordEncoded = personService.encodePassword(passClearText)
        def personInstance

        //Person #2
        personInstance = new Person(loginName:"admin",
                                    firstName:"Admin",
                                    lastName:"Powers",
                                    description:'''Every time the application starts it ensures that the 'admin' login name is available.
                                                        DO update the password and other details but keep the login name as 'admin'. ''',
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"admin@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(1))
    }

    def createBasePersons() {
    }

    def createDemoPersons() {
        //Person
        def passClearText = "pass"
        def passwordEncoded = personService.encodePassword(passClearText)
        def personInstance

        //Person #1 is system.
        //Person #2 is admin.

        //Person #3
        personInstance = new Person(loginName:"manager",
                                    firstName:"Demo",
                                    lastName:"Manager",
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"manager@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(2))
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToPersonGroups(PersonGroup.get(5))

        //Person #4
        personInstance = new Person(loginName:"user",
                                    firstName:"Demo",
                                    lastName:"User",
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"user@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToPersonGroups(PersonGroup.get(1))

        //Person #5
        personInstance = new Person(loginName:"craig",
                                    firstName:"Craig",
                                    lastName:"SuperSparky",
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"user@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToPersonGroups(PersonGroup.get(1))

        //Person #6
        personInstance = new Person(loginName:"john",
                                    firstName:"John",
                                    lastName:"SuperFitter",
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"user@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToPersonGroups(PersonGroup.get(2))

        //Person #7
        personInstance = new Person(loginName:"mann",
                                    firstName:"Production",
                                    lastName:"Mann",
                                    pass:passClearText,
                                    password:passwordEncoded,
                                    email:"user@example.com")
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToPersonGroups(PersonGroup.get(3))
    }

/***********************
START OF UTILITIES
***********************/

    def createDemoSites() {
        //Site
        def siteInstance

        siteInstance = new Site(name: "Creek Mill")
        saveAndTest(siteInstance)

        siteInstance = new Site(name: "Jasper Street Depot")
        saveAndTest(siteInstance)

        siteInstance = new Site(name: "River Press")
        saveAndTest(siteInstance)
    }

    def createDemoDepartments() {

        //Department
        def departmentInstance

        //Department #1
        departmentInstance = new Department(name: "Print Centre",
                                                                                    site: Site.get(1))
        saveAndTest(departmentInstance)

        //Department #2
        departmentInstance = new Department(name: "Pulp Mill 2",
                                                                                    site: Site.get(2))
        saveAndTest(departmentInstance)
    }

    def createBaseUnitsOfMeasure() {

        //UnitOfMeasure
        def unitOfMeasureInstance

        //UnitOfMeasure #1
        unitOfMeasureInstance = new UnitOfMeasure(name: "each")
        saveAndTest(unitOfMeasureInstance)

        //UnitOfMeasure #2
        unitOfMeasureInstance = new UnitOfMeasure(name: "meter(s)")
        saveAndTest(unitOfMeasureInstance)

        //UnitOfMeasure #3
        unitOfMeasureInstance = new UnitOfMeasure(name: "box(es)")
        saveAndTest(unitOfMeasureInstance)

        //UnitOfMeasure #4
        unitOfMeasureInstance = new UnitOfMeasure(name: "litre(s)")
        saveAndTest(unitOfMeasureInstance)

        //UnitOfMeasure #5
        unitOfMeasureInstance = new UnitOfMeasure(name: "kilogram(s)")
        saveAndTest(unitOfMeasureInstance)
    }

    def createBasePeriods() {

        //Period
        def periodInstance

        //Period #1
        periodInstance = new Period(period: "Day(s)")
        saveAndTest(periodInstance)

        //Period #2
        periodInstance = new Period(period: "Week(s)")
        saveAndTest(periodInstance)

        //Period #3
        periodInstance = new Period(period: "Month(s)")
        saveAndTest(periodInstance)

        //Period #4
        periodInstance = new Period(period: "Year(s)")
        saveAndTest(periodInstance)
    }

    def createBaseSupplierType() {

        // SupplierType
        def supplierTypeInstance

        // SupplierType #1
        supplierTypeInstance = new SupplierType(name: "OEM",
                                                                    description: "Original equipment supplier")
        saveAndTest(supplierTypeInstance)

        // SupplierType #2
        supplierTypeInstance = new SupplierType(name: "Local",
                                                                    description: "Local supplier")
        saveAndTest(supplierTypeInstance)
    }

    def createBaseManufacturerType() {

        // ManufacturerType
        def manufacturerTypeInstance

        // ManufacturerType #1
        manufacturerTypeInstance = new ManufacturerType(name: "OEM",
                                                                        description: "Original equipment manufacturer")
        saveAndTest(manufacturerTypeInstance)

        // ManufacturerType #2
        manufacturerTypeInstance = new ManufacturerType(name: "Alternate",
                                                                        description: "Not original equipment manufacturer")
        saveAndTest(manufacturerTypeInstance)

    }

    def createDemoSuppliers() {

        // Supplier
        def supplierInstance

        // Supplier #1
        supplierInstance = new Supplier(name: "OEM Distributors",
                                                                        supplierType: SupplierType.get(1))
        saveAndTest(supplierInstance)

        // Supplier #2
        supplierInstance = new Supplier(name: "Mex Holdings",
                                                                        supplierType: SupplierType.get(2))
        saveAndTest(supplierInstance)
    }

    def createDemoManufacturers() {

        // Manufacturer
        def manufacturerInstance

        // Manufacturer #1
        manufacturerInstance = new Manufacturer(name: "OEM Manufacturer",
                                                                        manufacturerType: ManufacturerType.get(1))
        saveAndTest(manufacturerInstance)

        // Manufacturer #2
        manufacturerInstance = new Manufacturer(name: "Laser Cutting Services Pty",
                                                                        manufacturerType: ManufacturerType.get(2))
        saveAndTest(manufacturerInstance)
    }

/*********************
START OF TASK
*********************/

    def createBaseTaskGroups() {
        //TaskGroup
        def taskGroupInstance

        taskGroupInstance = new TaskGroup(name:"Engineering Activites",
                                                                            description:"Engineering daily activities")
        saveAndTest(taskGroupInstance)

        taskGroupInstance = new TaskGroup(name:"Production Activites",
                                                                            description:"Production daily activities")
        saveAndTest(taskGroupInstance)

        taskGroupInstance = new TaskGroup(name:"New Projects",
                                                                            description:" ")
        saveAndTest(taskGroupInstance)
    }

    def createBaseTaskStatus() {

        //TaskStatus
        def taskStatusInstance

        taskStatusInstance = new TaskStatus(name:"Not Started") // #1
        saveAndTest(taskStatusInstance)

        taskStatusInstance = new TaskStatus(name:"In Progress") // #2
        saveAndTest(taskStatusInstance)

        taskStatusInstance = new TaskStatus(name:"Complete") // #3
        saveAndTest(taskStatusInstance)
    }

    def createBaseTaskPriorities() {

        //TaskPriority
        def taskPriorityInstance

        taskPriorityInstance = new TaskPriority(name:"Normal") // #1
        saveAndTest(taskPriorityInstance)

        taskPriorityInstance = new TaskPriority(name:"Low") // #2
        saveAndTest(taskPriorityInstance)

        taskPriorityInstance = new TaskPriority(name:"High") // #3
        saveAndTest(taskPriorityInstance)

        taskPriorityInstance = new TaskPriority(name:"Immediate") // #4
        saveAndTest(taskPriorityInstance)
    }

    def createBaseTaskTypes() {

        //TaskType
        def taskTypeInstance

        taskTypeInstance = new TaskType(name:"Unscheduled Breakin") // #1
        saveAndTest(taskTypeInstance)

        taskTypeInstance = new TaskType(name:"Preventative Maintenance") // #2
        saveAndTest(taskTypeInstance)

        taskTypeInstance = new TaskType(name:"Project") // #3
        saveAndTest(taskTypeInstance)

        taskTypeInstance = new TaskType(name:"Turnaround") // #4
        saveAndTest(taskTypeInstance)

        taskTypeInstance = new TaskType(name:"Production Run") // #5
        saveAndTest(taskTypeInstance)
    }

    def createBaseTaskModificationTypes() {

        //ModificationType
        def taskModificationTypeInstance
        taskModificationTypeInstance = new TaskModificationType(name:"Created").save()  // #1
        taskModificationTypeInstance = new TaskModificationType(name:"Started").save()  // #2
        taskModificationTypeInstance = new TaskModificationType(name:"Modified").save()  // #3
        taskModificationTypeInstance = new TaskModificationType(name:"Completed").save()  // #4
        taskModificationTypeInstance = new TaskModificationType(name:"Reopened").save()  // #5
        taskModificationTypeInstance = new TaskModificationType(name:"Trashed").save()  // #6
        taskModificationTypeInstance = new TaskModificationType(name:"Restored").save()  // #7
        taskModificationTypeInstance = new TaskModificationType(name:"Approved").save()  // #8
        taskModificationTypeInstance = new TaskModificationType(name:"Renege approval").save()  // #9
    }

    def createDemoTasks() {

        def taskResult
        def p = [:]

        //Task #1
        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                taskPriority:TaskPriority.get(2),
                taskType:TaskType.get(1),
                leadPerson:Person.get(2),
                description:"Check specific level sensor",
                comment:"Has been noted as problematic, try recalibrating.",
                targetStartDate: dateUtilService.today]

        taskResult = taskService.create(p)

        //Task #2
        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                taskPriority:TaskPriority.get(2),
                taskType:TaskType.get(1),
                leadPerson:Person.get(5),
                description:"Some follow-up work",
                comment:"Some help required",
                targetStartDate: dateUtilService.tomorrow,
                parentTask: Task.get(1)]

        taskResult = taskService.create(p)

        //Task #3
        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                taskPriority:TaskPriority.get(2),
                taskType:TaskType.get(1),
                leadPerson:Person.get(5),
                description:"A Sub Task can be created by setting the Parent Task value",
                comment:"Some help required",
                targetStartDate: dateUtilService.yesterday,
                parentTask: Task.get(1)]

        taskResult = taskService.create(p)

        //Task #4
        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                 taskPriority:TaskPriority.get(2),
                 taskType:TaskType.get(1),
                 leadPerson:Person.get(4),
                 description:"Replace sensor at next opportunity.",
                 comment:"Nothing else has worked.",
                targetStartDate: dateUtilService.oneWeekFromNow,
                parentTask: Task.get(1)]

        taskResult = taskService.create(p)

        //Task #5
        p = [taskGroup:TaskGroup.findByName("Production Activites"),
                 taskPriority:TaskPriority.get(2),
                 taskType:TaskType.get(5),
                 leadPerson:Person.get(6),
                 description:"Production Report",
                 comment:"Production report for specific production run or shift",
                targetStartDate: dateUtilService.today - 6]

        taskResult = taskService.create(p)

        //Task #6
        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                 taskPriority:TaskPriority.get(1),
                 taskType:TaskType.get(2),
                 leadPerson:Person.get(4),
                 description:"This is a recurring task",
                 comment:"If there is a parent task specified then this is a generated sub task, if there is a recurring schedule specified then this is a parent task.",
                targetStartDate: dateUtilService.today]

        taskResult = taskService.create(p)
    }

    def createBaseEntryTypes() {

        //EntryType
        def entryTypeInstance

        entryTypeInstance = new EntryType(name:"Fault") // #1
        saveAndTest(entryTypeInstance)

        entryTypeInstance = new EntryType(name:"Work Done") // #2
        saveAndTest(entryTypeInstance)

        entryTypeInstance = new EntryType(name:"Production Note") // #3
        saveAndTest(entryTypeInstance)

        entryTypeInstance = new EntryType(name:"Work Request") // #4
        saveAndTest(entryTypeInstance)
    }

    def createDemoEntries() {

        def entryResult
        def p = [:]

        //Entry #1
        p = [task: Task.get(1),
                entryType: EntryType.get(1),
                comment: "This level sensor is causing us trouble.",
                durationMinute: 20]

        entryResult = taskService.createEntry(p)

        //Entry #2
        p = [task: Task.get(1),
                entryType: EntryType.get(2),
                comment: "Cleaned sensor, see how it goes.",
                durationMinute: 30]

        entryResult = taskService.createEntry(p)

        //Entry #3
        p = [task: Task.get(1),
                entryType: EntryType.get(2),
                comment: "Checked up on it later and sensor is dropping out intermittently, created sub task to replace sensor.",
                durationMinute: 20]

        entryResult = taskService.createEntry(p)
    }

    def createDemoAssignedGroups() {

        //AssignedGroup
        def assignedGroupInstance

        //AssignedGroup #1
        assignedGroupInstance = new AssignedGroup(personGroup: PersonGroup.get(1),
                                                                                        task: Task.get(1),
                                                                                        estimatedHour: 2,
                                                                                        estimatedMinute: 30)
        saveAndTest(assignedGroupInstance)

        //AssignedGroup #2
        assignedGroupInstance = new AssignedGroup(personGroup: PersonGroup.get(2),
                                                                                        task: Task.get(1),
                                                                                        estimatedHour: 1,
                                                                                        estimatedMinute: 0)
        saveAndTest(assignedGroupInstance)
    }

    def createDemoAssignedPersons() {

        //AssignedPerson
        def assignedPersonInstance

        //AssignedPerson #1
        assignedPersonInstance = new AssignedPerson(person: Person.get(4),
                                                                                        task: Task.get(1),
                                                                                        estimatedHour: 1,
                                                                                        estimatedMinute: 20)
        saveAndTest(assignedPersonInstance)

        //AssignedPerson #2
        assignedPersonInstance = new AssignedPerson(person: Person.get(5),
                                                                                        task: Task.get(1),
                                                                                        estimatedHour: 3,
                                                                                        estimatedMinute: 30)
        saveAndTest(assignedPersonInstance)
    }

    def createDemoTaskRecurringSchedules() {

        //TaskRecurringSchedule
        def taskRecurringScheduleInstance

        //TaskRecurringSchedule #1
        taskRecurringScheduleInstance = new TaskRecurringSchedule(task: Task.get(1),
                                                                                                    recurEvery: 1,
                                                                                                    recurPeriod: Period.get(2),
                                                                                                    nextTargetStartDate: dateUtilService.today,
                                                                                                    generateAhead: 1,
                                                                                                    taskDuration: 2,
                                                                                                    taskDurationPeriod: Period.get(1),
                                                                                                    enabled: false)
        saveAndTest(taskRecurringScheduleInstance)

        //TaskRecurringSchedule #2
        taskRecurringScheduleInstance = new TaskRecurringSchedule(task: Task.get(6),
                                                                                                    recurEvery: 1,
                                                                                                    recurPeriod: Period.get(1),
                                                                                                    nextTargetStartDate: dateUtilService.today,
                                                                                                    generateAhead: 1,
                                                                                                    taskDuration: 1,
                                                                                                    taskDurationPeriod: Period.get(1),
                                                                                                    enabled: true)
        saveAndTest(taskRecurringScheduleInstance)
    }

/*************************
START OF INVENTORY
**************************/

    def createDemoInventoryStores() {

        //InventoryStore
        def inventoryStoreInstance

        inventoryStoreInstance = new InventoryStore(site: Site.get(1), name: "Store #1")
        saveAndTest(inventoryStoreInstance)

        inventoryStoreInstance = new InventoryStore(site: Site.get(2), name: "Store #2")
        saveAndTest(inventoryStoreInstance)
    }

    def createDemoInventoryLocations() {

        // InventoryLocation
        def inventoryLocation

        inventoryLocation = new InventoryLocation(inventoryStore: InventoryStore.get(1), name: "A1-2")
        saveAndTest(inventoryLocation)

        inventoryLocation = new InventoryLocation(inventoryStore: InventoryStore.get(1), name: "C55")
        saveAndTest(inventoryLocation)
    }

    def createDemoInventoryGroups() {

        //InventoryGroup
        def inventoryGroupInstance

        //InventoryGroup #1
        inventoryGroupInstance = new InventoryGroup(name: "Misc")
        saveAndTest(inventoryGroupInstance)

        //InventoryGroup #2
        inventoryGroupInstance = new InventoryGroup(name: "Electrical")
        saveAndTest(inventoryGroupInstance)

        //InventoryGroup #3
        inventoryGroupInstance = new InventoryGroup(name: "Mechanical")
        saveAndTest(inventoryGroupInstance)

        //InventoryGroup #4
        inventoryGroupInstance = new InventoryGroup(name: "Production")
        saveAndTest(inventoryGroupInstance)
    }

    def createBaseInventoryTypes() {

        //InventoryType
        def inventoryTypeInstance

        inventoryTypeInstance = new InventoryType(name: "Consumable")
        saveAndTest(inventoryTypeInstance)

        inventoryTypeInstance = new InventoryType(name: "Repairable")
        saveAndTest(inventoryTypeInstance)
    }

    def createBaseInventoryMovementTypes() {

        // InventoryMovementType
        def inventoryMovementTypeInstance

        // InventoryMovementType #1
        inventoryMovementTypeInstance = new InventoryMovementType(name: "Used",
                                                                                                                        incrementsInventory: false)
        saveAndTest(inventoryMovementTypeInstance)

        // InventoryMovementType #2
        inventoryMovementTypeInstance = new InventoryMovementType(name: "Repaired",
                                                                                                                        incrementsInventory: true)
        saveAndTest(inventoryMovementTypeInstance)

        // InventoryMovementType #3
        inventoryMovementTypeInstance = new InventoryMovementType(name: "Purchase Received",
                                                                                                                        incrementsInventory: true)
        saveAndTest(inventoryMovementTypeInstance)

        // InventoryMovementType #4
        inventoryMovementTypeInstance = new InventoryMovementType(name: "Correction Increase",
                                                                                                                        incrementsInventory: true)
        saveAndTest(inventoryMovementTypeInstance)

        // InventoryMovementType #5
        inventoryMovementTypeInstance = new InventoryMovementType(name: "Correction Decrease",
                                                                                                                        incrementsInventory: false)
        saveAndTest(inventoryMovementTypeInstance)
    }

    def createDemoInventoryItems() {

        //InventoryItem
        def inventoryItemInstance

        //InventoryItem #1
        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(1),
                                                                                    inventoryType: InventoryType.get(1),
                                                                                    unitOfMeasure: UnitOfMeasure.get(2),
                                                                                    inventoryLocation: InventoryLocation.get(1),
                                                                                    name: "Hemp rope",
                                                                                    description: "Natural hemp rope.",
                                                                                    unitsInStock: 2,
                                                                                    reorderPoint: 0)
        saveAndTest(inventoryItemInstance)

        //InventoryItem #2
        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(1),
                                                                                    inventoryType: InventoryType.get(1),
                                                                                    unitOfMeasure: UnitOfMeasure.get(2),
                                                                                    inventoryLocation: InventoryLocation.get(1),
                                                                                    name: "Cotton Rope 12mm",
                                                                                    description: "A soft natural rope made from cotton.",
                                                                                    alternateItems: InventoryItem.get(1),
                                                                                    unitsInStock: 2,
                                                                                    reorderPoint: 0)
        saveAndTest(inventoryItemInstance)

        //InventoryItem #3
        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(3),
                                                                                    inventoryType: InventoryType.get(1),
                                                                                    unitOfMeasure: UnitOfMeasure.get(1),
                                                                                    inventoryLocation: InventoryLocation.get(2),
                                                                                    name: "2305-2RS",
                                                                                    description: "Bearing 25x62x24mm double row self aligning ball",
                                                                                    unitsInStock: 3,
                                                                                    reorderPoint: 2)
        saveAndTest(inventoryItemInstance)

        //InventoryItem #4
        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(2),
                                                                                    inventoryType: InventoryType.get(1),
                                                                                    unitOfMeasure: UnitOfMeasure.get(1),
                                                                                    inventoryLocation: InventoryLocation.get(2),
                                                                                    name: "L1592-K10",
                                                                                    description: "10kW contactor",
                                                                                    unitsInStock: 4,
                                                                                    reorderPoint: 0)
        saveAndTest(inventoryItemInstance)

        //InventoryItem #5
        inventoryItemInstance = new InventoryItem(inventoryGroup: InventoryGroup.get(3),
                                                                                    inventoryType: InventoryType.get(1),
                                                                                    unitOfMeasure: UnitOfMeasure.get(1),
                                                                                    inventoryLocation: InventoryLocation.get(2),
                                                                                    name: "6205-ZZ",
                                                                                    description: "Bearing 25x52x15mm single row ball shielded",
                                                                                    unitsInStock: 5,
                                                                                    reorderPoint: 2)
        saveAndTest(inventoryItemInstance)
    }

/*******************
START OF ASSET
*******************/

    def createDemoLifePlan() {

        //LifePlan
        def lifeplanInstance

        lifeplanInstance = new LifePlan(name: "Initial Plan")
        saveAndTest(lifeplanInstance)
    }

    def createBaseMaintenancePolicies() {

        //MaintenancePolicy
        def maintenancePolicyInstance

        //MaintenancePolicy #1
        maintenancePolicyInstance = new MaintenancePolicy(name: "Fixed Time")
        saveAndTest(maintenancePolicyInstance)

        //MaintenancePolicy #2
        maintenancePolicyInstance = new MaintenancePolicy(name: "Condition Based Online")
        saveAndTest(maintenancePolicyInstance)

        //MaintenancePolicy #3
        maintenancePolicyInstance = new MaintenancePolicy(name: "Condition Based Offline")
        saveAndTest(maintenancePolicyInstance)

        //MaintenancePolicy #4
        maintenancePolicyInstance = new MaintenancePolicy(name: "Design Out")
        saveAndTest(maintenancePolicyInstance)

        //MaintenancePolicy #5
        maintenancePolicyInstance = new MaintenancePolicy(name: "Operate To Failure")
        saveAndTest(maintenancePolicyInstance)
    }

    def createDemoTaskProcedure() {

        //TaskProcedure
        def taskProcedureInstance

        taskProcedureInstance = new TaskProcedure(name: "Daily check")
        saveAndTest(taskProcedureInstance)
        taskProcedureInstance.addToTasks(Task.get(1))
    }

    def createDemoMaintenanceActions() {

        //MaintenanceAction
        def maintenanceActionInstance

        //MaintenanceAction #1
        maintenanceActionInstance = new MaintenanceAction(description: "Check all E-stops, activate E-stops S1-S12 and ensure machine cannot run",
                                                                                                        procedureStepNumber: 1,
                                                                                                        maintenancePolicy: MaintenancePolicy.get(1),
                                                                                                        taskProcedure: TaskProcedure.get(1))
        saveAndTest(maintenanceActionInstance)

        //MaintenanceAction #2
        maintenanceActionInstance = new MaintenanceAction(description: "Do more pushups",
                                                                                                        procedureStepNumber: 2,
                                                                                                        maintenancePolicy: MaintenancePolicy.get(1),
                                                                                                        taskProcedure: TaskProcedure.get(1))
        saveAndTest(maintenanceActionInstance)

        //MaintenanceAction #3
        maintenanceActionInstance = new MaintenanceAction(description: "Ok just one more pushup",
                                                                                                        procedureStepNumber: 3,
                                                                                                        maintenancePolicy: MaintenancePolicy.get(1),
                                                                                                        taskProcedure: TaskProcedure.get(1))
        saveAndTest(maintenanceActionInstance)
    }

    def createDemoSystemSections() {

        //SystemSection
        def systemSectionInstance

        //SystemSection #1
        systemSectionInstance = new SystemSection(name: "Press Section",
                                                                                    site: Site.get(1),
                                                                                    department: Department.get(1))
        saveAndTest(systemSectionInstance)

        //SystemSection #2
        systemSectionInstance = new SystemSection(name: "RO System",
                                                                                    site: Site.get(2),
                                                                                    department: Department.get(2))
        saveAndTest(systemSectionInstance)

        //SystemSection #3
        systemSectionInstance = new SystemSection(name: "Auxilliray Section",
                                                                                    site: Site.get(1),
                                                                                    department: Department.get(1))
        saveAndTest(systemSectionInstance)
    }

    def createDemoAssetTypes() {

        //AssetType
        def assetTypeInstance

        //AssetType #1
        assetTypeInstance = new AssetType(name: "Print Unit")
        saveAndTest(assetTypeInstance)

        //AssetType #2
        assetTypeInstance = new AssetType(name: "Reactor Tower")
        saveAndTest(assetTypeInstance)
    }

    def createDemoAssemblies() {

        //Assembly
        def assemblyInstance

        //Assembly #1
        assemblyInstance = new Assembly(name: "Print Couple",
                                                                        assetType: AssetType.get(1))
        saveAndTest(assemblyInstance)
//        assemblyInstance.addToMaintenanceActions(MaintenanceAction.get(1))

        //Assembly #2
        assemblyInstance = new Assembly(name: "Agitator",
                                                                        assetType: AssetType.get(2))
        saveAndTest(assemblyInstance)
    }

    def createDemoSubAssemblies() {

        //SubAssembly
        def subAssemblyInstance

        //SubAssembly #1
        subAssemblyInstance = new SubAssembly(name: "Cylinder",
                                                                                    assembly: Assembly.get(1))
        saveAndTest(subAssemblyInstance)

         //SubAssembly #2
        subAssemblyInstance = new SubAssembly(name: "Gearmotor",
                                                                                    assembly: Assembly.get(2))
        saveAndTest(subAssemblyInstance)
    }

    def createDemoComponentItems() {

        //ComponentItem
        def componentItemInstance

        //ComponentItem #1
        componentItemInstance = new ComponentItem(name: "Bearing",
                                                                                            subAssembly: SubAssembly.get(1))
        saveAndTest(componentItemInstance)

         //ComponentItem #2
        componentItemInstance = new ComponentItem(name: "Drive shaft oil seal",
                                                                                            subAssembly: SubAssembly.get(2))
        saveAndTest(componentItemInstance)
    }

    def createDemoAssets() {

        //Asset
        def assetInstance

        //Asset #1
        assetInstance = new Asset(name: "Print Unit 22",
                                                        assetType: AssetType.get(1),
                                                        systemSection: SystemSection.get(1))
        saveAndTest(assetInstance)
//        assetInstance.addToMaintenanceActions(MaintenanceAction.get(1))

        //Asset #2
        assetInstance = new Asset(name: "Print Unit 21",
                                                        assetType: AssetType.get(1),
                                                        systemSection: SystemSection.get(1))
        saveAndTest(assetInstance)

        //Asset #3
        assetInstance = new Asset(name: "Print Unit 23",
                                                        assetType: AssetType.get(1),
                                                        systemSection: SystemSection.get(1))
        saveAndTest(assetInstance)

        //Asset #4
        assetInstance = new Asset(name: "RO 1",
                                                        assetType: AssetType.get(2),
                                                        systemSection: SystemSection.get(2))
        saveAndTest(assetInstance)
    }

    def createBaseAssetExtenededAttributeTypes() {

        //AssetExtendedAttributeType
        def assetExtendedAttributeInstanceType

        //AssetExtendedAttributeType #1
        assetExtendedAttributeInstanceType = new AssetExtendedAttributeType(name: "Model Number")
        saveAndTest(assetExtendedAttributeInstanceType)

        //AssetExtendedAttributeType #2
        assetExtendedAttributeInstanceType = new AssetExtendedAttributeType(name: "Purchase Cost")
        saveAndTest(assetExtendedAttributeInstanceType)

        //AssetExtendedAttributeType #3
        assetExtendedAttributeInstanceType = new AssetExtendedAttributeType(name: "Serial Number")
        saveAndTest(assetExtendedAttributeInstanceType)

        //AssetExtendedAttributeType #4
        assetExtendedAttributeInstanceType = new AssetExtendedAttributeType(name: "Manufactured Date")
        saveAndTest(assetExtendedAttributeInstanceType)

        //AssetExtendedAttributeType #5
        assetExtendedAttributeInstanceType = new AssetExtendedAttributeType(name: "Location Description")
        saveAndTest(assetExtendedAttributeInstanceType)
    }

    def createDemoAssetExtenedAttributes() {

        //AssetExtendedAttribute
        def assetExtendedAttributeInstance

        //AssetExtendedAttribute #1
        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "PU Mark 2",
                                                                                                                    asset: Asset.get(1),
                                                                                                                    assetExtendedAttributeType: AssetExtendedAttributeType.get(1))
        saveAndTest(assetExtendedAttributeInstance)

        //AssetExtendedAttribute #2
        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "On the far side of Tank 5",
                                                                                                                    asset: Asset.get(1),
                                                                                                                    assetExtendedAttributeType: AssetExtendedAttributeType.get(5))
        saveAndTest(assetExtendedAttributeInstance)
    }


/****************************************
Call this function instead of .save()
*****************************************/
    private boolean saveAndTest(object) {
        if(!object.save()) {
//             DemoDataSuccessful = false
            log.error "'${object}' failed to save!"
            log.error object.errors
            return false
        }
        return true
    }
}
