/**
 * Copyright 2010 JBoss Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jbpm.task;

import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jbpm.task.AccessType;
import org.jbpm.task.AllowedToDelegate;
import org.jbpm.task.Attachment;
import org.jbpm.task.BooleanExpression;
import org.jbpm.task.Comment;
import org.jbpm.task.Deadline;
import org.jbpm.task.Deadlines;
import org.jbpm.task.Delegation;
import org.jbpm.task.Escalation;
import org.jbpm.task.I18NText;
import org.jbpm.task.Notification;
import org.jbpm.task.OrganizationalEntity;
import org.jbpm.task.PeopleAssignments;
import org.jbpm.task.Reassignment;
import org.jbpm.task.Status;
import org.jbpm.task.Task;
import org.jbpm.task.TaskData;
import org.jbpm.task.service.TaskServiceSession;

public class ModelPersistenceTest extends BaseTest {
    
    protected void setUp() throws Exception {
        super.setUp();                    
    }
    
    protected void tearDown() throws Exception {
        super.tearDown();
    }
    
    public void testfullHibernateRoundtripWithAdditionalMVELCheck() throws Exception {
        TaskServiceSession session = taskService.createSession();
        Task task1 = new Task();
        task1.setPriority( 100 );

        PeopleAssignments peopleAssignments = new PeopleAssignments();
        task1.setPeopleAssignments( peopleAssignments );

        peopleAssignments.setTaskInitiator( users.get(  "darth" ) );

        List<OrganizationalEntity> potentialOwners = new ArrayList<OrganizationalEntity>();
        peopleAssignments.setPotentialOwners( potentialOwners );
        potentialOwners.add( users.get( "bobba") );

        potentialOwners.add( users.get( "jabba") );

        List<OrganizationalEntity> excludedOwners = new ArrayList<OrganizationalEntity>();
        peopleAssignments.setExcludedOwners( excludedOwners );
        excludedOwners.add( users.get( "dalai" ) );

        excludedOwners.add( users.get( "christoper" ) );

        List<OrganizationalEntity> stakeholders = new ArrayList<OrganizationalEntity>();
        peopleAssignments.setTaskStakeholders( stakeholders );
        stakeholders.add( users.get( "stuart" ) );
        stakeholders.add( users.get( "jane" ) );

        List<OrganizationalEntity> businessAdmin = new ArrayList<OrganizationalEntity>();
        peopleAssignments.setBusinessAdministrators( businessAdmin );
        businessAdmin.add( users.get( "peter" ) );
        businessAdmin.add( users.get( "steve" ) );

        List<OrganizationalEntity> recipients = new ArrayList<OrganizationalEntity>();
        peopleAssignments.setRecipients( recipients );
        recipients.add( users.get( "sly" ) );
        recipients.add( users.get( "liz" ) );

        TaskData taskData = new TaskData();
        task1.setTaskData( taskData );
        
        taskData.setActualOwner( users.get( "liz" ) );
        taskData.setCreatedBy( users.get( "sly" ) );

        taskData.setActivationTime( new Date( 10000000 ) );
        taskData.setCreatedOn( new Date( 10000000 ) );
        taskData.setExpirationTime( new Date( 10000000 ) );
        taskData.setStatus( Status.Created );
        
        taskData.setDocumentAccessType( AccessType.Inline );
        taskData.setDocumentType( "mvel" );
        taskData.setDocumentContentId( 20 );

        List<Attachment> attachments = new ArrayList<Attachment>();
        taskData.setAttachments( attachments );

        Attachment attachment = new Attachment();
        attachment.setAccessType( AccessType.Inline );
        attachment.setAttachedAt( new Date( 10000000 ) );
        attachment.setAttachedBy( users.get( "liz" ) );
        attachment.setContentType( "text" );
        attachment.setName( "file.txt" );
        attachment.setSize( 5000);
        attachment.setAttachmentContentId( 5 );
        attachments.add( attachment );

        attachment = new Attachment();
        attachment.setAccessType( AccessType.Url );
        attachment.setAttachedAt( new Date( 10000000 ) );
        attachment.setAttachedBy( users.get( "liz" ) );
        attachment.setContentType( "text" );
        attachment.setName( "file2.txt" );
        attachment.setSize( 500 );
        attachment.setAttachmentContentId( 3 );
        attachments.add( attachment );

        List<Comment> comments = new ArrayList<Comment>();
        taskData.setComments( comments );
        Comment comment = new Comment();
        comment.setAddedBy( users.get( "peter" ) );
        comment.setAddedAt( new Date( 10000000 ) );
        comment.setText( "this is a short comment" );
        comments.add( comment );

        comment = new Comment();
        comment.setAddedBy( users.get( "steve" ) );
        comment.setAddedAt( new Date( 10000000 ) );
        comment.setText( "this is a loooooooooooooooooooooooooooooooooooooooooooooooong comment" );
        comments.add( comment );

        List<I18NText> names = new ArrayList<I18NText>();
        task1.setNames( names );
        List<I18NText> subjects = new ArrayList<I18NText>();
        task1.setSubjects( subjects );
        List<I18NText> descriptions = new ArrayList<I18NText>();
        task1.setDescriptions( descriptions );

        names.add( new I18NText( "en-UK",
                                 "This is my task name" ) );
        names.add( new I18NText( "en-DK",
                                 "Dies ist mein task Name" ) );

        subjects.add( new I18NText( "en-UK",
                                    "This is my task subject" ) );
        subjects.add( new I18NText( "en-DK",
                                    "Das ist mein task Thema" ) );

        descriptions.add( new I18NText( "en-UK",
                                        "This is my task description" ) );
        descriptions.add( new I18NText( "en-DK",
                                        "Das ist mein task Beschreibung" ) );

        Delegation delegation = new Delegation();
        task1.setDelegation( delegation );
        delegation.setAllowed( AllowedToDelegate.PotentialOwners );

        List<OrganizationalEntity> delegates = new ArrayList<OrganizationalEntity>();
        delegation.setDelegates( delegates );
        delegates.add( groups.get( "crusaders" ) );
        delegates.add( groups.get( "knightsTempler" ) );

        Deadlines deadlines = new Deadlines();
        task1.setDeadlines( deadlines );

        List<Deadline> startDeadlines = new ArrayList<Deadline>();
        deadlines.setStartDeadlines( startDeadlines );
        Deadline deadline = new Deadline();
        deadline.setEscalated( true );
        startDeadlines.add( deadline );
        deadline.setDate( new Date( 10000000 ) );
        List<I18NText> docs = new ArrayList<I18NText>();
        deadline.setDocumentation( docs );
        docs.add( new I18NText( "en-UK",
                                "Start Deadline documentation" ) );
        docs.add( new I18NText( "en-DK",
                                "Start Termin Dokumentation" ) );

        List<Escalation> escalations = new ArrayList<Escalation>();
        deadline.setEscalations( escalations );
        Escalation escalation = new Escalation();
        escalations.add( escalation );
        escalation.setName( "My Start Escalation" );

        List<BooleanExpression> constraints = new ArrayList<BooleanExpression>();
        escalation.setConstraints( constraints );
        constraints.add( new BooleanExpression( "mvel",
                                                "true" ) );

        List<Notification> notifications = new ArrayList<Notification>();
        escalation.setNotifications( notifications );

        Notification notification = new Notification();
        notifications.add( notification );
        notification.setPriority( 1000 );
        docs = new ArrayList<I18NText>();
        notification.setDocumentation( docs );
        docs.add( new I18NText( "en-UK",
                                "Start Notification documentation" ) );
        docs.add( new I18NText( "en-DK",
                                "Start Anmeldung Dokumentation" ) );

        businessAdmin = new ArrayList<OrganizationalEntity>();
        notification.setBusinessAdministrators( businessAdmin );
        businessAdmin.add( users.get( "bruce" ) );
        businessAdmin.add( users.get( "peter" ) );

        recipients = new ArrayList<OrganizationalEntity>();
        notification.setRecipients( recipients );
        recipients.add( users.get( "tony" ) );
        recipients.add( users.get( "darth" ) );

        names = new ArrayList<I18NText>();
        notification.setNames( names );
        subjects = new ArrayList<I18NText>();
        notification.setSubjects( subjects );
        descriptions = new ArrayList<I18NText>();
        notification.setDescriptions( descriptions );

        names.add( new I18NText( "en-UK",
                                 "This is my start notification name" ) );
        names.add( new I18NText( "en-DK",
                                 "Dies ist mein start anmeldung Name" ) );

        subjects.add( new I18NText( "en-UK", "This is my start notification subject" ) );
        subjects.add( new I18NText( "en-DK", "Das ist mein start anmeldung Thema" ) );

        descriptions.add( new I18NText( "en-UK", "This is my start notification description" ) );
        descriptions.add( new I18NText( "en-DK", "Das ist mein start anmeldung Beschreibung" ) );

        List<Reassignment> reassignments = new ArrayList<Reassignment>();
        escalation.setReassignments( reassignments );
        Reassignment reassignment = new Reassignment();
        reassignments.add( reassignment );

        docs = new ArrayList<I18NText>();
        reassignment.setDocumentation( docs );
        docs.add( new I18NText( "en-UK", "Start Reassignment documentation" ) );
        docs.add( new I18NText( "en-DK", "Start Neuzuweisung Dokumentation" ) );

        potentialOwners = new ArrayList<OrganizationalEntity>();
        reassignment.setPotentialOwners( potentialOwners );
        potentialOwners.add( users.get( "bobba" ) );
        potentialOwners.add( users.get( "luke" ) );
        
        List<Deadline> endDeadlines = new ArrayList<Deadline>();
        deadlines.setEndDeadlines( endDeadlines );
        deadline = new Deadline();
        deadline.setEscalated( true );
        endDeadlines.add( deadline );
        deadline.setDate( new Date( 10000000 ) );
        docs = new ArrayList<I18NText>();
        deadline.setDocumentation( docs );
        docs.add( new I18NText( "en-UK",
                                "End Deadline documentation" ) );
        docs.add( new I18NText( "en-DK",
                                "Ende Termin Dokumentation" ) );

        escalations = new ArrayList<Escalation>();
        deadline.setEscalations( escalations );
        escalation = new Escalation();
        escalations.add( escalation );
        escalation.setName( "My End Escalation" );

        constraints = new ArrayList<BooleanExpression>();
        escalation.setConstraints( constraints );
        constraints.add( new BooleanExpression( "mvel",
                                                "true" ) );

        notifications = new ArrayList<Notification>();
        escalation.setNotifications( notifications );

        notification = new Notification();
        notifications.add( notification );
        notification.setPriority( 1000 );
        docs = new ArrayList<I18NText>();
        notification.setDocumentation( docs );
        docs.add( new I18NText( "en-UK",
                                "End Notification documentation" ) );
        docs.add( new I18NText( "en-DK",
                                "Ende Anmeldung Dokumentation" ) );

        businessAdmin = new ArrayList<OrganizationalEntity>();
        notification.setBusinessAdministrators( businessAdmin );
        businessAdmin.add( users.get( "bobba" ) );
        businessAdmin.add( users.get( "darth" ) );

        recipients = new ArrayList<OrganizationalEntity>();
        notification.setRecipients( recipients );
        recipients.add( users.get( "liz" ) );
        recipients.add( users.get( "jane" ) );

        names = new ArrayList<I18NText>();
        notification.setNames( names );
        subjects = new ArrayList<I18NText>();
        notification.setSubjects( subjects );
        descriptions = new ArrayList<I18NText>();
        notification.setDescriptions( descriptions );

        names.add( new I18NText( "en-UK",
                                 "This is my end notification name" ) );
        names.add( new I18NText( "en-DK",
                                 "Dies ist mein ende anmeldung Name" ) );

        subjects.add( new I18NText( "en-UK", "This is my end notification subject" ) );
        subjects.add( new I18NText( "en-DK", "Das ist mein ende anmeldung Thema" ) );

        descriptions.add( new I18NText( "en-UK", "This is my end notification description" ) );
        descriptions.add( new I18NText( "en-DK", "Das ist mein ende anmeldung Beschreibung" ) );

        reassignments = new ArrayList<Reassignment>();
        escalation.setReassignments( reassignments );
        reassignment = new Reassignment();
        reassignments.add( reassignment );

        docs = new ArrayList<I18NText>();
        reassignment.setDocumentation( docs );
        docs.add( new I18NText( "en-UK", "End Reassignment documentation" ) );
        docs.add( new I18NText( "en-DK", "Ende Neuzuweisung Dokumentation" ) );

        potentialOwners = new ArrayList<OrganizationalEntity>();
        reassignment.setPotentialOwners( potentialOwners );
        potentialOwners.add( users.get( "stuart" ) );
        potentialOwners.add( users.get( "dalai" ) );        

        session.addTask( task1, null );
        
        session.dispose();        
        session = taskService.createSession();
        
        Task task2 = session.getTask( task1.getId( ) );       
        assertNotSame( task1,
                       task2 );
        assertEquals( task1,
                      task2 );
        
        Reader reader = new InputStreamReader( getClass().getResourceAsStream( "FullyPopulatedTask.mvel" ) );
        Map  vars = new HashMap();
        vars.put( "users", users );
        vars.put( "groups", groups );          
        vars.put( "bytes1", new byte[]{1, 0, 0, 1} ); 
        Task task3= (Task) eval( reader, vars );               
        
        assertNotSame( task1,
                       task3 );
        assertEquals( task1,
                      task3 );
        session.dispose();
    }    

}
