/**
* 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 authService
    def taskService
    def dateUtilService
    def appConfigService
    def assignedGroupService
    def assignedPersonService

/*******************************************
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()
        createBaseDefinitions()
        createBaseUnitsOfMeasure()
        createBasePeriods()
        createBaseSupplierTypes()
        createBaseManufacturerTypes()
        createBaseAddressTypes()
        createBaseContactTypes()

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

        // Inventory
        createBaseInventoryTypes()
        createBaseInventoryMovementTypes()

        // Assets
        createBaseExtenededAttributeTypes()
        createBaseMaintenancePolicies()

        // 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()
        createDemoSections()
        createDemoAssetTree()
        createDemoAssetExtenedAttributes()

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

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

    def createAdminAuthority() {
        def authInstance

        // Authority #1
        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

        // Authority #2
        authInstance = new Authority(description:"Business Manager, grants full management access.",
                                        authority:"ROLE_Manager")
        saveAndTest(authInstance)

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

        // Authority #4
        authInstance = new Authority(description:"Task Manager",
                                        authority:"ROLE_TaskManager")
        saveAndTest(authInstance)

        // Authority #5
        authInstance = new Authority(description:"Task User",
                                        authority:"ROLE_TaskUser")
        saveAndTest(authInstance)

        // Authority #6
        authInstance = new Authority(description:"Inventory Manager",
                                        authority:"ROLE_InventoryManager")
        saveAndTest(authInstance)

        // Authority #7
        authInstance = new Authority(description:"Inventory User",
                                        authority:"ROLE_InventoryUser")
        saveAndTest(authInstance)

        // Authority #8
        authInstance = new Authority(description:"Asset Manager",
                                        authority:"ROLE_AssetManager")
        saveAndTest(authInstance)

        // Authority #9
        authInstance = new Authority(description:"Asset User",
                                        authority:"ROLE_AssetUser")
        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 = authService.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)
        saveAndTest(personInstance)
    }

    def createAdminPerson() {
        //Person
        def passClearText = "pass"
        def passwordEncoded = authService.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)
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(1))
    }

    def createBasePersons() {
    }

    def createDemoPersons() {
        //Person
        def passClearText = "pass"
        def passwordEncoded = authService.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)
        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)
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToAuthorities(Authority.get(5))
        personInstance.addToAuthorities(Authority.get(7))
        personInstance.addToAuthorities(Authority.get(9))
        personInstance.addToPersonGroups(PersonGroup.get(1))

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

        //Person #6
        personInstance = new Person(loginName:"john",
                                    firstName:"John",
                                    lastName:"SuperFitter",
                                    pass:passClearText,
                                    password:passwordEncoded)
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToAuthorities(Authority.get(5))
        personInstance.addToAuthorities(Authority.get(7))
        personInstance.addToAuthorities(Authority.get(9))
        personInstance.addToPersonGroups(PersonGroup.get(2))

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

        //Person #7
        personInstance = new Person(loginName:"testmanager",
                                    firstName:"Test",
                                    lastName:"Manager",
                                    pass:passClearText,
                                    password:passwordEncoded)
        saveAndTest(personInstance)
        personInstance.addToAuthorities(Authority.get(3))
        personInstance.addToAuthorities(Authority.get(4))
        personInstance.addToAuthorities(Authority.get(6))
        personInstance.addToAuthorities(Authority.get(8))
        personInstance.addToPersonGroups(PersonGroup.get(3))
    }

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

    //These can redefined by the site at deployment time.
    /// @todo: build an admin view so that only the value (definition) can be changed.
    def createBaseDefinitions() {
        appConfigService.set("Department Definition", "A department as recongised by accounting.")
        appConfigService.set("Site Definition", "The plant, work or production site.")
        appConfigService.set("Section Definition", "A logical grouping of assets, which may be an area, system or process \
                                            as determined by design.")
        appConfigService.set("Asset Definition",
                                            "The complete asset as it is known on the site. \
                                            Often purchased as a whole with the primary purpose of returning value by performing a function. \
                                            An asset is made up of 1 or more sub assets and performs a complete function as specified by the designer.")
        appConfigService.set("Asset Sub Item 1 Name",
                                            "Sub Asset")
        appConfigService.set("Asset Sub Item 1 Definition",
                                            "A machine that performs part of a complete asset's function and often has a model number.")
        appConfigService.set("Asset Sub Item 2 Name",
                                            "Functional Assembly")
        appConfigService.set("Asset Sub Item 2 Definition",
                                            "Functional Assemblies are taken from the designer's functional list for the sub asset and are made up of sub \
                                            assemblies that together perform that function.")
        appConfigService.set("Asset Sub Item 3 Name",
                                            "Sub Assembly Group")
        appConfigService.set("Asset Sub Item 3 Definition",
                                            "Group or type of part.")
        appConfigService.set("Asset Sub Item 4 Name",
                                            "Component Item")
        appConfigService.set("Asset Sub Item 4 Definition",
                                            "The smallest part that would be analysed for failure.")
    }

    def createDemoSites() {
        //Site
        def siteInstance

        siteInstance = new Site(name: "CSM",
                                                    description: "Creek Side Mill")
        saveAndTest(siteInstance)

        siteInstance = new Site(name: "Jasper Street Depot",
                                                    description: "Storage depot on Jasper Street.")
        saveAndTest(siteInstance)

        siteInstance = new Site(name: "River Press",
                                                    description: "Printing press site")
        saveAndTest(siteInstance)
    }

    def createDemoDepartments() {

        //Department
        def departmentInstance

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

        //Department #2
        departmentInstance = new Department(name: "Pulp Mill",
                                                                                description: "Business Department",
                                                                                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 createBaseSupplierTypes() {

        // SupplierType
        def supplierTypeInstance

        // SupplierType #1
        supplierTypeInstance = new SupplierType(name: "Unknown",
                                                                    description: "Unknown supplier type")
        saveAndTest(supplierTypeInstance)

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

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

    def createBaseManufacturerTypes() {

        // ManufacturerType
        def manufacturerTypeInstance

        // ManufacturerType #1
        manufacturerTypeInstance = new ManufacturerType(name: "Unknown",
                                                                        description: "Unknown manufacturer type")
        saveAndTest(manufacturerTypeInstance)

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

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

    }

    def createBaseAddressTypes() {

        // AddressType
        def addressTypeInstance

        // AddressType #1
        addressTypeInstance = new AddressType(name: "Postal",
                                                                                description: "A postal address.")
        saveAndTest(addressTypeInstance)

        // AddressType #2
        addressTypeInstance = new AddressType(name: "Physical",
                                                                                description: "A physical address.")
        saveAndTest(addressTypeInstance)

        // AddressType #3
        addressTypeInstance = new AddressType(name: "Postal & Physical",
                                                                                description: "An address that is both the postal and physical address.")
        saveAndTest(addressTypeInstance)

        // AddressType #4
        addressTypeInstance = new AddressType(name: "Invoice",
                                                                                description: "An address to send invoices to.")
        saveAndTest(addressTypeInstance)

        // AddressType #5
        addressTypeInstance = new AddressType(name: "Delivery",
                                                                                description: "An address to send deliveries to.")
        saveAndTest(addressTypeInstance)
    }

    def createBaseContactTypes() {

        // ContactType
        def contactTypeInstance

        // ContactType #1
        contactTypeInstance = new ContactType(name: "Email",
                                                                                description: "Email address.")
        saveAndTest(contactTypeInstance)

        // ContactType #2
        contactTypeInstance = new ContactType(name: "Alternate Email",
                                                                                description: "Alternate email address.")
        saveAndTest(contactTypeInstance)

        // ContactType #3
        contactTypeInstance = new ContactType(name: "Mobile",
                                                                                description: "Modile phone number.")
        saveAndTest(contactTypeInstance)

        // ContactType #4
        contactTypeInstance = new ContactType(name: "Work Phone",
                                                                                description: "Work phone number.")
        saveAndTest(contactTypeInstance)

        // ContactType #5
        contactTypeInstance = new ContactType(name: "Home Phone",
                                                                                description: "Home phone number.")
        saveAndTest(contactTypeInstance)

        // ContactType #6
        contactTypeInstance = new ContactType(name: "Work Fax",
                                                                                description: "Work fax number.")
        saveAndTest(contactTypeInstance)

        // ContactType #7
        contactTypeInstance = new ContactType(name: "Home Fax",
                                                                                description: "Home fax number.")
        saveAndTest(contactTypeInstance)

        // ContactType #8
        contactTypeInstance = new ContactType(name: "Web Site",
                                                                                description: "Web site address.")
        saveAndTest(contactTypeInstance)

        // ContactType #9
        contactTypeInstance = new ContactType(name: "Person",
                                                                                description: "Contact person.")
        saveAndTest(contactTypeInstance)
    }

    def createDemoSuppliers() {

        // Supplier
        def supplierInstance

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

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

    def createDemoManufacturers() {

        // Manufacturer
        def manufacturerInstance

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

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

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

    def createBaseTaskGroups() {
        //TaskGroup
        def taskGroupInstance

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

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

        //TaskGroup #3
        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 createBaseTaskBudgetStatus() {

        //TaskBudgetStatus
        def taskBudgetStatusInstance

        taskBudgetStatusInstance = new TaskBudgetStatus(name:"Unplanned") // #1
        saveAndTest(taskBudgetStatusInstance)

        taskBudgetStatusInstance = new TaskBudgetStatus(name:"Planned") // #2
        saveAndTest(taskBudgetStatusInstance)
    }

    def createBaseTaskTypes() {

        //TaskType
        def taskTypeInstance

        taskTypeInstance = new TaskType(name:"Immediate Callout") // #1
        saveAndTest(taskTypeInstance)

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

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

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

        taskTypeInstance = new TaskType(name:"Predictive Maintenance") // #5
        saveAndTest(taskTypeInstance)

        taskTypeInstance = new TaskType(name:"Project") // #6
        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
        taskModificationTypeInstance = new TaskModificationType(name:"Modified (Assigned Groups)").save()  // #10
        taskModificationTypeInstance = new TaskModificationType(name:"Modified (Assigned Persons)").save()  // #11
        taskModificationTypeInstance = new TaskModificationType(name:"Modified (Flagged for attention)").save()  // #12
        taskModificationTypeInstance = new TaskModificationType(name:"Modified (Attention flag cleared)").save()  // #13
    }

    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:"Level sensor not working",
                comment:"Has been noted as problematic, try recalibrating.",
                targetStartDate: dateUtilService.today]

        taskResult = taskService.save(p)

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

        taskResult = taskService.save(p)

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

        taskResult = taskService.save(p)

        //Task #4
        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                 taskPriority:TaskPriority.get(2),
                 taskType:TaskType.get(2),
                 leadPerson:Person.get(4),
                 description:"Please replace sensor at next available opportunity.",
                 comment:"Nothing else has worked. So we now require the part to be replaced.",
                targetStartDate: dateUtilService.oneWeekFromNow,
                parentTask: Task.get(1)]

        taskResult = taskService.save(p)

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

        taskResult = taskService.save(p)

        //Task #6
        p = [taskGroup:TaskGroup.findByName("Engineering Activites"),
                 taskPriority:TaskPriority.get(4),
                 taskType:TaskType.get(3),
                 leadPerson:Person.get(4),
                 description:"This is a recurring preventative maintenance 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.save(p)
    }

    def createBaseEntryTypes() {

        //EntryType
        def entryTypeInstance

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

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

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

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

        entryTypeInstance = new EntryType(name:"Work Request") // #5
        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.saveEntry(p)

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

        entryResult = taskService.saveEntry(p)

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

        entryResult = taskService.saveEntry(p)
    }

    def createDemoAssignedGroups() {

        def result
        def p = [:]

        //AssignedGroup #1
        p = [personGroup: PersonGroup.get(1),
                task: Task.get(1),
                estimatedHour: 2,
                estimatedMinute: 30]
        result = assignedGroupService.save(p)

        //AssignedGroup #2
        p = [personGroup: PersonGroup.get(2),
                task: Task.get(1),
                estimatedHour: 1,
                estimatedMinute: 0]
        result = assignedGroupService.save(p)
    }

    def createDemoAssignedPersons() {

        def result
        def p = [:]

        //AssignedPerson #1
        p = [person: Person.get(4),
                task: Task.get(1),
                estimatedHour: 1,
                estimatedMinute: 20]
        result = assignedPersonService.save(p)

        //AssignedPerson #2
        p = [person: Person.get(5),
                task: Task.get(1),
                estimatedHour: 3,
                estimatedMinute: 30]
        result = assignedPersonService.save(p)
    }

    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(2), 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 createBaseExtenededAttributeTypes() {

        //ExtendedAttributeType
        def extendedAttributeTypeInstance

        //ExtendedAttributeType #1
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Model Number")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #2
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Purchase Cost")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #3
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Serial Number")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #4
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Manufactured Date")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #5
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Location Description")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #6
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Cost Centre")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #7
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Cost Code")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #8
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Manufacturer's Number")
        saveAndTest(extendedAttributeTypeInstance)

        //ExtendedAttributeType #9
        extendedAttributeTypeInstance = new ExtendedAttributeType(name: "Inventory Number")
        saveAndTest(extendedAttributeTypeInstance)
    }

    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)

        //MaintenancePolicy #6
        maintenancePolicyInstance = new MaintenancePolicy(name: "Regulatory Requirement")
        saveAndTest(maintenancePolicyInstance)

        //MaintenancePolicy #7
        maintenancePolicyInstance = new MaintenancePolicy(name: "Hidden Function Test")
        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 createDemoSections() {

        //Section
        def sectionInstance

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

        //Section #2
        sectionInstance = new Section(name: "CSM-Delig",
                                                                description: "Pulp Delignification",
                                                                site: Site.get(1),
                                                                department: Department.get(2))
        saveAndTest(sectionInstance)

        //Section #3
        sectionInstance = new Section(name: "CSM-Aux",
                                                                description: "Auxilliary Section",
                                                                site: Site.get(1),
                                                                department: Department.get(1))
        saveAndTest(sectionInstance)
    }

    def createDemoAssetTree() {

        //Asset
        def assetInstance

        //Asset #1
        def assetInstance1 = new Asset(name: "Print Tower 22",
                                                                description: "Complete Printing Asset #22",
                                                                section: Section.get(1))
        saveAndTest(assetInstance1)
//        assetInstance.addToMaintenanceActions(MaintenanceAction.get(1))

        //Asset #2
        def assetInstance2 = new Asset(name: "Print Tower 21",
                                                                description: "Complete Printing Asset #21",
                                                                section: Section.get(1))
        saveAndTest(assetInstance2)

        //Asset #3
        def assetInstance3 = new Asset(name: "Print Tower 23",
                                                                description: "Complete Printing Asset #23",
                                                                section: Section.get(1))
        saveAndTest(assetInstance3)

        //Asset #4
        def assetInstance4 = new Asset(name: "C579",
                                                                description: "RO #1",
                                                                section: Section.get(2))
        saveAndTest(assetInstance4)

        //AssetSubItem
        def assetSubItemInstance

        //AssetSubItem #1 Level1
        def assetSubItemInstance1 = new AssetSubItem(name: "Print Tower",
                                                                                            description: "Common sub asset.")
        saveAndTest(assetSubItemInstance1)

        // Add assetSubItemInstance1 to some assets.
        assetInstance1.addToAssetSubItems(assetSubItemInstance1)
        assetInstance2.addToAssetSubItems(assetSubItemInstance1)
        assetInstance3.addToAssetSubItems(assetSubItemInstance1)

        //AssetSubItem #2 Level1
        def assetSubItemInstance2 = new AssetSubItem(name: "C579-44",
                                                                                            description: "Tanks and towers")
        saveAndTest(assetSubItemInstance2)

        // Add assetSubItemInstance2 to some assets.
        assetInstance4.addToAssetSubItems(assetSubItemInstance2)

        //AssetSubItem #3 Level1
        def assetSubItemInstance3 = new AssetSubItem(name: "C579-20",
                                                                                            description: "Control Loops")
        saveAndTest(assetSubItemInstance3)

        // Add assetSubItemInstance3 to some assets.
        assetInstance4.addToAssetSubItems(assetSubItemInstance3)

        //AssetSubItem #4 Level2
        assetSubItemInstance = new AssetSubItem(name: "C579-TK-0022",
                                                                                            description: "Blow Tank",
                                                                                            parentItem: AssetSubItem.get(2))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #5 Level2
        assetSubItemInstance = new AssetSubItem(name: "C579-TK-0023",
                                                                                            description: "Reactor Tower",
                                                                                            parentItem: AssetSubItem.get(2))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #6 Level2
        assetSubItemInstance = new AssetSubItem(name: "Print Unit",
                                                                                    description: "Print Unit - Common Level 2 sub item.",
                                                                                    parentItem: AssetSubItem.get(1))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #7 Level2
        assetSubItemInstance = new AssetSubItem(name: "1925365",
                                                                                    description: "Agitator",
                                                                                    parentItem: AssetSubItem.get(4))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #8 Level2
        assetSubItemInstance = new AssetSubItem(name: "1925366",
                                                                                    description: "Scraper",
                                                                                    parentItem: AssetSubItem.get(4))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #9 Level3
        assetSubItemInstance = new AssetSubItem(name: "Motor",
                                                                                    description: "Motor - Level 3 sub item",
                                                                                    parentItem: AssetSubItem.get(6))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #10 Level3
        assetSubItemInstance = new AssetSubItem(name: "Gearbox",
                                                                                    description: "Gearbox - Level 3 sub item, gearbox",
                                                                                    parentItem: AssetSubItem.get(6))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #11 Level4
        assetSubItemInstance = new AssetSubItem(name: "DS Bearing",
                                                                                    description: "Drive Side Bearing",
                                                                                    parentItem: AssetSubItem.get(9))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #12 Level4
        assetSubItemInstance = new AssetSubItem(name: "NDS Bearing",
                                                                                    description: "Non Drive Side Bearing",
                                                                                    parentItem: AssetSubItem.get(9))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #13 Level2
        assetSubItemInstance = new AssetSubItem(name: "C579-F-0001",
                                                                                    description: "Weak Caustic Flow",
                                                                                    parentItem: AssetSubItem.get(3))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #14 Level3
        assetSubItemInstance = new AssetSubItem(name: "C579-FT-0002",
                                                                                    description: "Weak Caustic Flow Transmitter",
                                                                                    parentItem: AssetSubItem.get(13))
        saveAndTest(assetSubItemInstance)

        //AssetSubItem #15 Level3
        assetSubItemInstance = new AssetSubItem(name: "C579-PT-0003",
                                                                                    description: "Weak Caustic Pressure Transmitter",
                                                                                    parentItem: AssetSubItem.get(13))
        saveAndTest(assetSubItemInstance)
    } // createDemoAssetTree()

    def createDemoAssetExtenedAttributes() {

        //AssetExtendedAttribute
        def assetExtendedAttributeInstance

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

        //AssetExtendedAttribute #2
        assetExtendedAttributeInstance = new AssetExtendedAttribute(value: "On the far side of Tank 5",
                                                                                                                    asset: Asset.get(1),
                                                                                                                    extendedAttributeType: ExtendedAttributeType.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
    }
}
