package org.apache.turbine.flux.modules.actions.group;

import org.apache.velocity.context.Context;

import org.apache.turbine.om.security.Group;
import org.apache.turbine.util.RunData;
import org.apache.turbine.util.security.EntityExistsException;
import org.apache.turbine.util.security.UnknownEntityException;
import org.apache.turbine.util.security.GroupSet;
import org.apache.turbine.services.security.TurbineSecurity;
import org.apache.turbine.flux.modules.actions.FluxAction;
import org.apache.turbine.om.security.peer.GroupPeer;
import org.apache.turbine.services.resources.TurbineResources;
import org.apache.turbine.util.security.AccessControlList;
import org.apache.turbine.om.security.User;
import org.apache.turbine.om.security.Role;
import org.apache.turbine.util.db.Criteria;
import org.apache.turbine.flux.tools.RoleTool;
import org.apache.turbine.flux.tools.CMSGroup;
import org.apache.turbine.flux.tools.GroupTool;
import org.apache.turbine.flux.tools.TemplateTool;

import java.util.List;
import java.util.HashMap;
import java.util.Vector;
import java.util.StringTokenizer;
import java.io.File;

import com.workingdogs.village.Record;
import com.workingdogs.village.Value;

/**
   @author <a href="mailto:kokchoon78@yahoo.com">Ling Kok Choon</a>
   last modofied: 31-8-2001
 */
public class GroupAction extends FluxAction
{

    /**
       validate Group Name
       last modified : 31-8-2001
     */
     public boolean validateGroupName ( String groupName )
     {
  	   boolean pass = true ;
  	   StringTokenizer st = new StringTokenizer( groupName );
  	   if (st.countTokens() > 1 )
   	   {
   		  pass = false ;
   	   }

  	   if ( groupName == null || groupName.length() == 0 || groupName.length() > 32 )
   	   {
   		  pass = false ;
   	   }

   	   return ( pass );
     }

    /**
       validate Group Link Name
       last modified : 31-8-2001
     */
     public boolean validateLinkName ( String linkName )
     {
  	   boolean pass = true ;
  	   if ( linkName == null || linkName.length() == 0 || linkName.length() > 99 )
   	   {
   		  pass = false ;
   	   }

   	   return ( pass );
     }


     /**
        add a new folder to the database and to the file system.
        last modified: 31-8-2001
     */
     public void doAdd ( RunData data, Context context )
       throws Exception
     {
		 RoleTool rt = new RoleTool();

         String mode = data.getParameters().getString("mode");

         if ( mode == null )
         {
			 mode = "" ;
		 }

		 Group group = TurbineSecurity.getNewGroup(null);
         data.getParameters().setProperties(group);

		 String p_name = data.getParameters().getString("p_name");
		 //note: p_name = parent's group id

		 String label     = data.getParameters().getString("label");
		 String username  = data.getParameters().getString("username");
		 Role[] userRoles = rt.getRoles ( data.getUser() );

		 String my_type   = data.getParameters().getString("add_type");
		 String link_name = rt.changeSpecial( data.getParameters().getString("link_name") );

         System.out.println("Link Name : " + link_name );

		 boolean error = false;

		 if ( !validateGroupName ( label ) || !rt.checkSpecial( label ) )
		 {
			 error = true;
			 context.put("GroupLabel_Error","true");
		 }

		 if ( !validateLinkName ( link_name ) )
		 {
		 	 error = true;
		 	 context.put("LinkName_Error","true");
		 }

		 if ( error )
		 {
			 context.put("label", label);
			 context.put("link_name", link_name);
			 context.put("p_name", p_name);
			 context.put("group", group);

			 context.put("errorTemplate", "/screens/error/GroupDataError.vm");

             if ( mode.equals("webpage") )
             {
				 setTemplate(data, "/publish/Add_Webpage.vm");
			 }
			 else
			 {
			 	setTemplate(data, "/group/Add_Folder.vm");
			 }
		 }
		 else
		 {
			 doAddFileDir ( data, context, 0, group, p_name, label,
			                username, userRoles, my_type, link_name , mode );

			 context.put("added", "true");
			 context.put("groupName", label );
		 }

	 }






    /**
      Delete created files - xml files, picture files
      last modified: 6-9-2001
    */
     public void deleteFiles( String groupName , String root , String endPurePath )
     {

         GroupTool gt = new GroupTool();
         String endPath = gt.formatPath( endPurePath.replace('/' , '\\'));
		 //for pic dir
		 File picDir = new File (root.concat("\\pic").concat(endPath));
		 //System.out.println("picDir : " + picDir );

		 File picList[] = picDir.listFiles();
		 for ( int i = 0 ; i < picList.length ; i ++ )
		 {
			 if ( picList[i].isFile() )
			 {
				 String fileName = picList[i].getName();
				 //to get the actual pic to delete, fileName.length() + 2 because to count the number pic e.g. GroupName00.pic
				 //System.out.println("fileName : " + fileName );
				 //System.out.println("groupName : " + groupName );
				 //System.out.println("char : " + fileName.charAt( groupName.length() + 2 ) );

				 if ( fileName.startsWith( groupName ) && fileName.charAt( groupName.length() + 2 ) == '.' )
				 {
					 picList[i].delete();
				 }
			 }//end if ( fileList...
		 }//end for

		 //for xml dir
		 File xmlDir = new File (root.concat("\\xml").concat(endPath));
		 File xmlList[] = xmlDir.listFiles();
		 for ( int i = 0 ; i < xmlList.length ; i ++ )
		 {
		  if ( xmlList[i].isFile() )
		  {
		 	 String fileName = xmlList[i].getName();

		 	 if ( fileName.equals( groupName.concat("_final.xml") ) )
		 	 {
		 		 xmlList[i].delete();
		 	 }
		  }//end if ( fileList...
		 }//end for


		 //for source dir
		 File sourceDir = new File (root.concat("\\sources").concat(endPath));
		 File sourceList[] = sourceDir.listFiles();
		 for ( int i = 0 ; i < sourceList.length ; i ++ )
		 {
		   if ( sourceList[i].isFile() )
		   {
		  	 String fileName = sourceList[i].getName();
		  	 if ( fileName.equals( groupName.concat(".rtf") ) )
		  	 {
		  		 sourceList[i].delete();
		  	 }
		   }//end if ( fileList...
		  }//end for

	 }



    /**
       delete created folder
       last modified: 10 - 9 -2001
     */
	public void deleteDir( String myPath , String root )
	  throws Exception
	{
		GroupTool gt = new GroupTool();

		String other_dir = null ;

		other_dir = TurbineResources.getString("directories");

		StringTokenizer st = new StringTokenizer( other_dir , "," );

		while ( st.hasMoreTokens() )
		{
		   //substring the parent path, so we can apend the other dir to it
		   String parentEndPart = myPath.substring( root.length() );

           String path = null;

		   path = root.concat(st.nextToken()).concat(parentEndPart);
		   //System.out.println("Path:" + path );
		   File f = new File( path );
		   f.delete();
	     }
	}



	 /**
	   add a file or dir to the file system
	   last modified: 31-8-2001

	   Note: p_name is the group index, name is the group / file's label / name
	 */
    public void doAddFileDir ( RunData data, Context context, int status, Group group, String p_name, String name, String username,
                               Role[] userRoles, String my_type, String link_name , String mode )
         throws Exception
    {
		if ( status == 1 )
		{
			group = TurbineSecurity.getNewGroup(null);
		}

		GroupTool gt = new GroupTool();

        List infoList = gt.getAllGroupsInfo();

		int p_id = Integer.parseInt(p_name);

		int nc = gt.getChildNumber( p_id , infoList );


		// here we check the duplication happen in a same folder / parent

		if ( gt.isDuplicated( p_id , name , infoList ) )
		{
			 context.put("label", name );
			 context.put("link_name", link_name);
			 context.put("p_name", p_name);
			 context.put("group", group);

			 context.put("errorTemplate", "/screens/error/GroupDuplicated.vm");

             if ( mode.equals("webpage") )
             {
				 setTemplate(data, "/publish/Add_Webpage.vm");
			 }
			 else
			 {
			 	setTemplate(data, "/group/Add_Folder.vm");
			 }
		}
		else
		{

            CMSGroup parentCMSGroup = gt.getCMSGroup ( p_id , infoList );
			String p_path = parentCMSGroup.getPath();
			String p_type = parentCMSGroup.getType();

            String groupName = Integer.toString( parentCMSGroup.getGroup_id() ).concat(".").concat(name);
     		group.setName ( groupName );

			//check if the parent is a file
			if ( p_type.equals("FILE") )
			{
    			 context.put("label", name );
    			 context.put("link_name", link_name);
    			 context.put("p_name", p_name);
    			 context.put("group", group);

    			 context.put("errorTemplate", "/screens/error/AddDirError.vm");

	             if ( mode.equals("webpage") )
	             {
				    setTemplate(data, "/publish/Add_Webpage.vm");
				 }
				 else
				 {
				 	setTemplate(data, "/group/Add_Folder.vm");
				 }
			}
			else
			{

                TurbineSecurity.addGroup ( group );

                TemplateTool tt = new TemplateTool();
                int newid = tt.getGroupID( groupName );
                String newidS = Integer.toString( newid );

				String path = p_path.concat("/").concat(name);
				CMSGroup cmsGroup = new CMSGroup();
				cmsGroup.setGroup_id( newid );
				cmsGroup.setLevel_id( parentCMSGroup.getLevel_id() + 1 );
				cmsGroup.setParent_id( parentCMSGroup.getGroup_id() );
				cmsGroup.setLabel( name );
				cmsGroup.setRanking( nc + 1 );
                cmsGroup.setPath( path );
                cmsGroup.setType( my_type );
                cmsGroup.setLink_label( link_name );
                cmsGroup.setStatus( "NEW" );

                gt.saveCMSGroup ( cmsGroup );
                infoList.add ( cmsGroup );

				try
				{

					addFileDir ( p_path , cmsGroup , my_type , name );

					User u = TurbineSecurity.getUser( username );

					//grant user ( who create this folder ) to this file or dir
					for ( int i = 0 ; i < userRoles.length ; i ++ )
					{
						TurbineSecurity.grant( u , TurbineSecurity.getGroup( groupName ) , userRoles[i] );
					}

                    if ( my_type.equals("FILE") )
                    {
						grantTemplate ( newidS , Integer.toString( p_id ) ) ;
					}

					if ( status == 0 && my_type.equals("DIR") )
					{
					   //here to add the **_index ( home webpage )
					   doAddFileDir ( data, context, 1, null, newidS , "index", username,
					   userRoles, "FILE", "Home" , mode );
					 }
				}
		        catch (EntityExistsException eee)
		        {
					System.out.println("add web page error : " + eee.toString() );
					}

			}

		}
	}


    /**
       Add file or dir to file system
       last modified: 31-8-2001
    */
    public void addFileDir ( String parent, CMSGroup cmsGroup , String type , String label)
      throws Exception
    {
		String other_dir = null ;

		if ( type.equals("DIR") )
		{
			GroupTool gt = new GroupTool();

			other_dir = TurbineResources.getString("directories");

	    	String root = gt.getContext ( cmsGroup );
            System.out.println("root :" + root );
            System.out.println("parent :" + parent );

	    	StringTokenizer st = new StringTokenizer ( other_dir , "," );
	    	while ( st.hasMoreTokens() )
	    	{
	    		String parentEndPart = parent.substring( root.length() );

	    		String path = null ;
	    		if ( type.equals("DIR") )
	    		{
	     			path = root.concat( st.nextToken() ).concat ( parentEndPart ).concat("/").concat( label );
	    		}

                System.out.println("path:" + path );

	    		File f = new File ( path );
	    		f.mkdir();

	    	}
		}
	}


    public void doDelete(RunData data, Context context)
        throws Exception
    {

		//Note : currently the delete function only change folder / files status from database

		String g_name = data.getParameters().getString("g_name");
        String label = data.getParameters().getString("label");

		updateGroup ( g_name, "DELETE" );
		context.put("deleted", "true");
	    context.put("groupName", label );
    }


    //****************************************************************
    //do Undelete web page


    public void doUndelete(RunData data, Context context)
        throws Exception
    {

		String g_name = data.getParameters().getString("g_name");
        String label = data.getParameters().getString("label");

		updateGroup ( g_name, "UNDELETE" );
		context.put("undeleted", "true");
	    context.put("groupName", label );
    }


   //****************************************************************
   //to change the group type to "DELETED" for delete
   //to change the group type to "FILE" for undelete

   public void updateGroup( String groupName , String function)
     throws Exception
   {
	    String status = null;

	    if ( function.equals("DELETE") )
	    {
        	status = "DELETED";
		}
		else
		{
			status = "CREATED";
		}

        GroupTool gt = new GroupTool();
        gt.changeGroupStatus( Integer.parseInt(groupName) , status );


    }


	/**
	  delete a Group from system
	  last modified: 10-9-2001
     */
	public void doClear ( RunData data, Context context )
		throws Exception
	{
		GroupTool gt = new GroupTool();

		String groupLabel = data.getParameters().getString( "label" );
		String p_name = data.getParameters().getString("p_name");
        String called_by = data.getParameters().getString("called_by");

        //System.out.println("p_name:" + p_name);
        List infoList = gt.getAllGroupsInfo();
        CMSGroup cmsGroup = gt.getCMSGroup( Integer.parseInt(p_name) , infoList );

		Group group = TurbineSecurity.getGroup( gt.getGName( cmsGroup ) );

		String path = cmsGroup.getPath();
		String type = cmsGroup.getType();


        String root = gt.getContext( cmsGroup );
		String parentEndPart = path.substring( root.length() );

		int cn = gt.getChildNumber( Integer.parseInt(p_name) , infoList );

		if ( cn != 0 )
		{
		   context.put("label", groupLabel );
		   //context.put("p_name", p_name );
		   context.put("errorTemplate", "/screens/error/DeleteGroupError.vm");
		   if ( called_by.equals("clear") )
		   {
			   setTemplate(data, "/publish/Delete_Webpage.vm");
		   }
		   else
		   {
		     	setTemplate(data, "/group/Folder_List.vm");
		   }
		}
		else
		{
				TemplateTool tt = new TemplateTool();

                gt.revokeAllGroupMapping ( p_name );
                tt.revokeAllLink ( p_name );
                tt.revokeAll ( p_name );
                tt.revokeAllTSelection ( p_name );
                tt.revokeAllHeader ( p_name );

   				if ( type.equals("DIR"))
   				{
				    deleteDir( path , root );
				}
				else
				{
					deleteFiles( cmsGroup.getLabel() , root , parentEndPart );
				}

   				TurbineSecurity.removeGroup ( group );
                gt.removeCMSGroup( Integer.parseInt(p_name) );

                 context.put("clear","true");
              	 context.put("label", groupLabel );

 			     if ( called_by.equals("clear") )
		   		 {
			 	   setTemplate(data, "/publish/Delete_Webpage.vm");
		     	 }
		   		 else
		   		 {
		   		  	setTemplate(data, "/group/Folder_List.vm");
		   		 }
		 }
	}




    /**
       Insert a web page to the system

    public void doInsert ( RunData data , Context context )
       throws Exception
    {
		Group group = TurbineSecurity.getNewGroup(null);
		data.getParameters().setProperties ( group );

		String p_name = data.getParameters().getString("p_name");
		String label   = data.getParameters().getString("label");
		String username = data.getParameters().getString("username");
		String my_type = data.getParameters().getString("add_type");
		String insertTo_name = data.getParameters().getString("insertTo_name");
		String link_name = data.getParameters().getString("link_name");

		String p_index = p_name;

		String insertTo_index = insertTo_name;

		RoleTool rt  = new RoleTool();
		GroupTool gt = new GroupTool();

		Role[] userRoles = rt.getRoles ( data.getUser () );
		int lastIndexNumber = gt.getLastIndexNumber ( insertTo_index );

		String index = p_index.concat(".").concat( Integer.toString( lastIndexNumber + 1 ) );

		HashMap hm = gt.getGroupObjectData ( p_index );
		String p_path = gt.getGroupInfo ( hm , "GROUP_PATH" );
		String p_type = gt.getGroupInfo ( hm , "GROUP_TYPE");

		String path = p_path.concat("/").concat(label);


		 boolean error = false;

		 if ( !validateGroupName ( label ) )
		 {
			 error = true;
			 context.put("GroupLabel_Error","true");
		 }

		 if ( !validateLinkName ( link_name ) )
		 {
		 	 error = true;
		 	 context.put("LinkName_Error","true");
		 }

		 if ( error )
		 {
			 context.put("label", label);
			 context.put("link_name", link_name);
			 context.put("p_name", p_name);
			 context.put("group", group);

			 context.put("errorTemplate", "/screens/error/GroupDataError.vm");

//             if ( mode.equals("webpage") )
//             {
				 setTemplate(data, "/publish/Add_Webpage.vm");
//			 }
//			 else
//			 {
//			 	setTemplate(data, "/group/Add_Folder.vm");
//			 }
		 }
		 else
		 {

			GroupSet gs = gt.getChildGroups( p_index );
		    Group[] childGroups = gs.getGroupsArray();

			// here we check the duplication happen in a same folder / parent
			boolean duplicated = false;
			for ( int i = 0 ; i < childGroups.length ; i ++ )
			{
				HashMap hmm1 = gt.getGroupObjectData ( childGroups[i].getName() );
				String childLabel = gt.getGroupInfo ( hmm1 , "GROUP_LABEL" );

				if ( label.equals( childLabel ) )
				{
					duplicated = true;
					i = childGroups.length;
				}
			}

			if ( duplicated )
			{
				 context.put("label", label );
				 context.put("link_name", link_name);
				 context.put("p_name", p_name);
				 context.put("group", group);

				 context.put("errorTemplate", "/screens/error/GroupDuplicated.vm");

//	             if ( mode.equals("webpage") )
//	             {
					 setTemplate(data, "/publish/Add_Webpage.vm");
//				 }
//				 else
//				 {
//				 	setTemplate(data, "/group/Add_Folder.vm");
//				 }
			}
			else
			{


				HashMap hmm = new HashMap();
				hmm.put ( "GROUP_LINK_NAME" , link_name );
				hmm.put ( "GROUP_TYPE" , my_type );
				hmm.put ( "GROUP_PATH" , path );
				hmm.put ( "GROUP_LABEL" , label );

				group.setName ( index );

				//try
				//{
					Vector childVector = new Vector();
					Vector result = gt.getGroupsOrderBy();

					if ( !result.isEmpty() )
					{
						for ( int i = 0 ; i < result.size() ; i ++ )
						{
							Group resultg = (Group)result.get(i);
							String group_index = resultg.getName();

							if ( group_index.startsWith( p_index ) && gt.getLevel( group_index ) == gt.getLevel ( insertTo_index ) )
							{
								childVector.add ( resultg );
							}
						}
					}

					//we change the index first, b4 insert the group
					for ( int i = childVector.size() - 1 ; i <= lastIndexNumber ; i -- )
					{
						Group change_g = ( Group )childVector.get(i);

						String change_index = change_g.getName();
						System.out.println("change_index : " + change_index );

						int lastNumber = gt.getLastIndexNumber ( change_index );
						System.out.println("lastNumber : " + lastNumber );
						String newIndex = p_index.concat(".").concat( Integer.toString( lastNumber + 1 ) );
                        System.out.println("newIndex : " + newIndex );

						change_g.setName ( newIndex );

						TurbineSecurity.saveGroup( change_g );

					}


                    if ( my_type.equals("FILE") )
                    {
						grantTemplate ( index , p_index ) ;
					}


					TurbineSecurity.addGroup ( group );
					String query = "UPDATE TURBINE_GROUP SET OBJECTDATA='" + hmm +
					               "' WHERE GROUP_NAME='" + index + "'";

					GroupPeer pp = new GroupPeer();
					pp.executeStatement ( query );

					//addFileDir ( p_path , index , my_type );

					User u = TurbineSecurity.getUser ( username );

					for ( int i = 0 ; i < userRoles.length ; i ++ )
					{
						TurbineSecurity.grant ( u, TurbineSecurity.getGroup( index ) , userRoles[i] );
					}

					context.put ( "inserted" , "true" );
					context.put ( "groupName" , label );

				//}
				//catch( Exception eee )
				//{
				//	System.out.println("doInsert Error : " + eee.toString() );
				//}
			}
		}
	}

    /**
       when add / insert a web page, grant template mapping from the parent folder
    */
    public void grantTemplate ( String ownIndex , String parentIndex )
       throws Exception
    {
		TemplateTool tt = new TemplateTool();
		String[] template_id = tt.getTemplatesInfo ( "ID" );


		for ( int i = 0 ; i < template_id.length ; i ++ )
		{
			if ( tt.hasTemplate ( parentIndex , template_id[i] ) )
			{
				tt.grant( ownIndex , Integer.parseInt(template_id[i]) );
			}
		}
	}



    /**
     * Implement this to add information to the context.
     *
     * @param data Turbine information.
     * @param context Context for web pages.
     * @exception Exception, a generic exception.
     */
    public void doPerform( RunData data,Context context )
        throws Exception
    {
        System.out.println("Running do perform!");
        data.setMessage("Can't find the requested action!");
    }
}
