/*
 * Copyright (C) 2003-2009 eXo Platform SAS.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see<http://www.gnu.org/licenses/>.
 */

package org.exoplatform.services.wcm.javascript;

import java.io.ByteArrayOutputStream;
import java.util.Date;

import javax.jcr.Node;
import javax.jcr.NodeIterator;

import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.wcm.BaseWCMTestCase;
import org.exoplatform.services.wcm.portal.LivePortalManagerService;
import org.exoplatform.services.wcm.utils.WCMCoreUtils;
import org.exoplatform.web.application.javascript.JavascriptConfigService;

/**
 * The Class TestXJavaScriptService.
 * 
 * Created by The eXo Platform SAS
 * Author : Ngoc.Tran
 * ngoc.tran@exoplatform.com
 * July 15, 2008
 */
public class TestXJavaScriptService extends BaseWCMTestCase {

	/** The javascript service. */
	private XJavascriptService javascriptService;
	
	/** The Constant WEB_CONTENT_NODE_NAME. */
	private static final String WEB_CONTENT_NODE_NAME = "webContent";
	
	private Node documentNode;
	private Node sharedJsNode;
	
	SessionProvider sessionProvider;
	
	/* (non-Javadoc)
	 * @see org.exoplatform.services.wcm.BaseWCMTestCase#setUp()
	 */
	public void setUp() throws Exception {
		
		super.setUp();
		sessionProvider = WCMCoreUtils.getSystemSessionProvider();
		javascriptService = getService(XJavascriptService.class);
		documentNode = (Node) session.getItem("/sites content/live/classic/documents");
		sharedJsNode = (Node) session.getItem("/sites content/live/classic/js");
	}
	
	/**
	 * Test get active java script_01.
	 * 
	 * When parameter input is null
	 */
	public void testGetActiveJavaScript_01() {
		try {
			javascriptService.getActiveJavaScript(null);
		} catch (Exception e) {
			assertNotNull(e.getStackTrace());
		}
	}

	/**
	 * Test get active java script_02.
	 * 
	 * When node input node type is not exo:webcontent.
	 */
	public void testGetActiveJavaScript_02() {
		try {
			Node nodeInput = documentNode.addNode(WEB_CONTENT_NODE_NAME);
			session.save();
			String jsData = javascriptService.getActiveJavaScript(nodeInput);
			assertEquals("", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	/**
	 * Test get active java script_03.
	 * 
	 * When node input is exo:webcontent and have some child node but does not content mixin type.
	 */
	public void testGetActiveJavaScript_03() {
		try {
			Node webContent = documentNode.addNode(WEB_CONTENT_NODE_NAME, "exo:webContent");
			
			webContent.setProperty("exo:title", WEB_CONTENT_NODE_NAME);
			webContent.addNode("jsFolder", "exo:jsFolder");
			session.save();
			
			String jsData = javascriptService.getActiveJavaScript(webContent);

			assertEquals("", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	/**
	 * Test get active java script_04.
	 * 
	 * When node input is exo:webcontent and have some child node but have mixin type does not exo:jsFile.
	 */
	public void testGetActiveJavaScript_04() {
		try {
			Node webContent = documentNode.addNode(WEB_CONTENT_NODE_NAME, "exo:webContent");
			webContent.setProperty("exo:title", WEB_CONTENT_NODE_NAME);
			Node jsFolder = webContent.addNode("jsFolder", "exo:jsFolder");
	    Node jsNode = jsFolder.addNode("default.js", "nt:file");
	    
	    Node jsContent = jsNode.addNode("jcr:content", "nt:resource");
	    jsContent.setProperty("jcr:encoding", "UTF-8");
	    jsContent.setProperty("jcr:mimeType", "text/javascript");
	    jsContent.setProperty("jcr:lastModified", new Date().getTime());
	    jsContent.setProperty("jcr:data", "This is the default.js file.");
	    session.save();

			String jsData = javascriptService.getActiveJavaScript(webContent);
			assertEquals("This is the default.js file.", jsData);
		} catch(Exception e) {
			fail();
		}
	}

	/**
	 * Test get active java script_05.
	 * 
	 * Child node have properties normal and value of exo:active is:
	 * - "exo:active": false
	 */
	public void testGetActiveJavaScript_05() {
		try {
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, null);
			Node jsNode = webContent.getNode("js").getNode("default.js");
			jsNode.setProperty("exo:active", false);
			session.save();
			
			String jsData = javascriptService.getActiveJavaScript(webContent);
			assertEquals("", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	/**
	 * Test get active java script_06.
	 * 
	 * Child node have properties normal and value of jcr:mimeType is:
	 * - "jcr:mimeType": text/html
	 */
	public void testGetActiveJavaScript_06() {
		try {
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, null);
			Node jsNode = webContent.getNode("js").getNode("default.js");
			Node jsContent = jsNode.getNode("jcr:content");
			jsContent.setProperty("jcr:mimeType", "text/html");
			session.save();
			
			String jsData = javascriptService.getActiveJavaScript(webContent);
			assertEquals("This is the default.js file.", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	/**
	 * Test get active java script_07.
	 * 
	 * Child node have properties normal and value of jcr:mimeType is:
	 * - "jcr:mimeType": text/javascript
	 */
	public void testGetActiveJavaScript_07() {
		try {
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, null);
			Node jsNode = webContent.getNode("js").getNode("default.js");
			Node jsContent = jsNode.getNode("jcr:content");
			jsContent.setProperty("jcr:mimeType", "text/javascript");
			session.save();
			
			String jsData = javascriptService.getActiveJavaScript(webContent);
			assertEquals("This is the default.js file.", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	/**
	 * Test get active java script_08.
	 * 
	 * Child node have properties normal and value of jcr:mimeType is:
	 * - "jcr:mimeType": application/x-javascript
	 */
	public void testGetActiveJavaScript_08() {
		try {
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, null);
			Node jsNode = webContent.getNode("js").getNode("default.js");
			Node jsContent = jsNode.getNode("jcr:content");
			jsContent.setProperty("jcr:mimeType", "application/x-javascript");
			session.save();
			
			String jsData = javascriptService.getActiveJavaScript(webContent);
			assertEquals("This is the default.js file.", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	/**
	 * Test get active java script_09.
	 * 
	 * Child node have properties normal and value of jcr:mimeType is:
	 * - "jcr:mimeType": text/ecmascript
	 */
	public void testGetActiveJavaScript_09() {
		try {
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, null);
			Node jsNode = webContent.getNode("js").getNode("default.js");
			Node jsContent = jsNode.getNode("jcr:content");
			jsContent.setProperty("jcr:mimeType", "text/ecmascript");
			session.save();
			
			String jsData = javascriptService.getActiveJavaScript(webContent);
			assertEquals("This is the default.js file.", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	/**
	 * Test get active java script_10.
	 * 
	 * Child node have properties normal and value of jcr:data is ""
	 */
	public void testGetActiveJavaScript_10() {
		try {
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, null);
			Node jsNode = webContent.getNode("js").getNode("default.js");
			Node jsContent = jsNode.getNode("jcr:content");
			jsContent.setProperty("jcr:data", "");
			session.save();
			
			String jsData = javascriptService.getActiveJavaScript(webContent);
			assertEquals("", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	/**
	 * Test get active java script_11.
	 * 
	 * Child node have properties normal and value of jcr:data is:
	 * - "jcr:data": This is the default.js file.
	 */
	public void testGetActiveJavaScript_11() {
		try {
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, null);
			Node jsNode = webContent.getNode("js").getNode("default.js");
			Node jsContent = jsNode.getNode("jcr:content");
			jsContent.setProperty("jcr:data", "This is the default.js file.");
			session.save();
			
			String jsData = javascriptService.getActiveJavaScript(webContent);
			assertEquals("This is the default.js file.", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	/**
	 * Test get active java script_12.
	 * 
	 * Child node have properties normal and value of jcr:mimeType is:
	 * - "jcr:data": alert('Test method getActiveJavaScript()');.
	 */
	public void testGetActiveJavaScript_12() {
		try {
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, "alert('Test method getActiveJavaScript()');");
			session.save();
			String jsData = javascriptService.getActiveJavaScript(webContent);
			assertEquals("alert('Test method getActiveJavaScript()');", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	/**
	 * Test get active java script_13.
	 * 
	 * In case normal
	 */
	public void testGetActiveJavaScript_13() {
		try {
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, null);
			String jsData = javascriptService.getActiveJavaScript(webContent);
			assertEquals("This is the default.js file.", jsData);
		} catch (Exception e) {
			fail();
		}
	}

	/**
	 * Test update portal js on modify_01.
	 * When node input is null.
	 */
	public void testUpdatePortalJSOnModify_01() {
		try {
		  JavascriptConfigService configService = null;
		  Node portalNode = findPortalNode(sessionProvider, documentNode);
			javascriptService.updatePortalJSOnModify(portalNode, null);
      session.save();
      configService = getService(JavascriptConfigService.class);
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      configService.writeMergedJavascript(baos);
      baos.close();
      String jsData = baos.toString("UTF-8");
      assertEquals("", jsData);
		} catch(Exception e) {
		  fail();
		}
	}
	
	/**
	 * Test update portal js on modify_02.
	 * When Node input does not jsFile.
	 */
	public void testUpdatePortalJSOnModify_02() {
		try {
		  Node portalNode = findPortalNode(sessionProvider, documentNode);
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, null);
			createSharedJsNode(sharedJsNode);
			Node jsFolder = webContent.getNode("js");
			javascriptService.updatePortalJSOnModify(portalNode, jsFolder);
		} catch(Exception e) {
			assertNotNull(e.getStackTrace());
		}
	}
	
	/**
	 * Test update portal js on modify_03.
	 * When node input have jcr:data is "".
	 */
	public void testUpdatePortalJSOnModify_03() {
		try {
			JavascriptConfigService configService = null;
			Node portalNode = findPortalNode(sessionProvider, documentNode);
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, "");
			createSharedJsNode(sharedJsNode);
			Node jsNode = webContent.getNode("js").getNode("default.js");
			javascriptService.updatePortalJSOnModify(portalNode, jsNode);
			session.save();
			
			configService = getService(JavascriptConfigService.class);
		    ByteArrayOutputStream baos = new ByteArrayOutputStream();
		    configService.writeMergedJavascript(baos);
		    baos.close();
		    String jsData = baos.toString("UTF-8");
			assertEquals("", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	/**
	 * Test update portal js on modify_04.
	 * When node input have jcr:data is "When perform testUpdatePortalJSOnModify...".
	 *//*
	public void testUpdatePortalJSOnModify_04() {
		try {
			JavascriptConfigService configService = null;
			Node portalNode = findPortalNode(sessionProvider, documentNode);
			createSharedJsNode(sharedJsNode);
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, "When perform testUpdatePortalJSOnModify...");
			Node jsNode = webContent.getNode("js").getNode("default.js");
			javascriptService.updatePortalJSOnModify(portalNode, jsNode);
			session.save();
			configService = getService(JavascriptConfigService.class);
			String jsData = new String(configService.getMergedJavascript());
			assertEquals("\nWhen perform testUpdatePortalJSOnModify...", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	*//**
	 * Test update portal js on modify_05.
	 * When node input have jcr:data is "alert('testUpdatePortalJSOnModify...');".
	 *//*
	public void testUpdatePortalJSOnModify_05() {
		try {
			JavascriptConfigService configService = null;
			Node portalNode = findPortalNode(sessionProvider, documentNode);
      createSharedJsNode(sharedJsNode);
      Node js = sharedJsNode.getNode("sharedJsFile.js");
      js.setProperty("exo:priority", 2);
      Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, "alert('testUpdatePortalJSOnModify...');");
      Node jsNode = webContent.getNode("js").getNode("default.js");
      javascriptService.updatePortalJSOnModify(portalNode, jsNode);
			session.save();
			
			configService = getService(JavascriptConfigService.class);
			String jsData = new String(configService.getMergedJavascript());
			assertEquals("\nalert('testUpdatePortalJSOnModify...');", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	public void testUpdatePortalJSOnModify_06() {
    try {
      JavascriptConfigService configService = null;
      WCMConfigurationService configurationService = WCMCoreUtils.getService(WCMConfigurationService.class);;
      LivePortalManagerService livePortalManagerService = getService(LivePortalManagerService.class);
      String sharedPortalName = configurationService.getSharedPortalName(REPO_NAME);
      Node portal = livePortalManagerService.getLivePortal(sessionProvider, sharedPortalName);
      Node sharedNode = (Node) session.getItem("/sites content/live/" + sharedPortalName + "/js");
      Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, "alert('testUpdatePortalJSOnModify...');");
      Node jsNode = webContent.getNode("js").getNode("default.js");
      createSharedJsNode(sharedNode);
      Node js = sharedNode.getNode("sharedJsFile.js");
      js.setProperty("exo:priority", 1);
      javascriptService.updatePortalJSOnModify(portal, jsNode);
      session.save();
      String jsData = "";
      configService = getService(JavascriptConfigService.class);
      jsData = new String(configService.getMergedJavascript());
      assertEquals("\nThis is the default.js file.alert('testUpdatePortalJSOnModify...');", jsData);
      
      session.save();
    } catch(Exception e) {
      fail();
    }
  }*/
	
	/**
	 * Test update portal js on remove_01.
	 * When node input is null.
	 */
	public void testUpdatePortalJSOnRemove_01() {
		try {
		  Node portalNode = findPortalNode(sessionProvider, documentNode);
		  createSharedJsNode(sharedJsNode);
			javascriptService.updatePortalJSOnRemove(portalNode, null);
		} catch(Exception e) {
			assertNotNull(e.getStackTrace());
		}
	}
	
	/**
	 * Test update portal js on remove_03.
	 * When Node input does not jsFile.
	 */
	public void testUpdatePortalJSOnRemove_03() {
		try {
			Node portalNode = findPortalNode(sessionProvider, documentNode);
			createSharedJsNode(sharedJsNode);
			javascriptService.updatePortalJSOnRemove(portalNode, sharedJsNode);
		} catch(Exception e) {
			assertNotNull(e);
		}
	}
	
	/**
	 * Test update portal js on remove_04.
	 * When node input have jcr:data is "".
	 *//*
	public void testUpdatePortalJSOnRemove_04() {
		try {
			JavascriptConfigService configService = null;
			Node portalNode = findPortalNode(sessionProvider, documentNode);
			createSharedJsNode(sharedJsNode);
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, "");
			Node jsNode = webContent.getNode("js").getNode("default.js");
			configService = getService(JavascriptConfigService.class);
			String jsData = "";
			javascriptService.updatePortalJSOnRemove(portalNode, jsNode);
			session.save();
			jsData = new String(configService.getMergedJavascript());
			assertEquals("\nThis is the default.js file.", jsData);
		} catch(Exception e) {
			fail();
		}
	}
	
	*//**
	 * Test update portal js on remove_05.
	 * When node input have jcr:data is "alert('testUpdatePortalJSOnModify...');".
	 *//*
	public void testUpdatePortalJSOnRemove_05() {
		try {
			JavascriptConfigService configService = null;
			Node portalNode = findPortalNode(sessionProvider, documentNode);
			
			Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, "alert('testUpdatePortalJSOnModify...');");
			Node jsNode = webContent.getNode("js").getNode("default.js");
			createSharedJsNode(sharedJsNode);
			Node js = sharedJsNode.getNode("sharedJsFile.js");
			js.setProperty("exo:priority", 1);
			session.save();
			String jsData = "";
			configService = getService(JavascriptConfigService.class);
			javascriptService.updatePortalJSOnRemove(portalNode, jsNode);
			session.save();
			jsData = new String(configService.getMergedJavascript());
			assertEquals("\nThis is the default.js file.This is the default.js file.", jsData);
		} catch(Exception e) {
			fail();
		}
	}

	*//**
   * Test update portal js on remove_06.
   * When portal node is shared portal.
   *//*
  public void testUpdatePortalJSOnRemove_06() {
    try {
      JavascriptConfigService configService = null;
      WCMConfigurationService configurationService = WCMCoreUtils.getService(WCMConfigurationService.class);;
      LivePortalManagerService livePortalManagerService = getService(LivePortalManagerService.class);
      String sharedPortalName = configurationService.getSharedPortalName(REPO_NAME);
      Node portal = livePortalManagerService.getLivePortal(sessionProvider, sharedPortalName);
      Node sharedNode = (Node) session.getItem("/sites content/live/" + sharedPortalName + "/js");
      Node webContent = createWebcontentNode(documentNode, WEB_CONTENT_NODE_NAME, null, null, "alert('testUpdatePortalJSOnModify...');");
      Node jsNode = webContent.getNode("js").getNode("default.js");
      createSharedJsNode(sharedNode);
      String jsData = "";
      configService = getService(JavascriptConfigService.class);
      javascriptService.updatePortalJSOnRemove(portal, jsNode);
      session.save();
      jsData = new String(configService.getMergedJavascript());
      assertEquals("\nThis is the default.js file.alert('testUpdatePortalJSOnModify...');", jsData);
      session.save();
    } catch(Exception e) {
      fail();
    }
  }*/
	
  private Node findPortalNode(SessionProvider sessionProvider, Node child) throws Exception{    
    LivePortalManagerService livePortalManagerService = getService(LivePortalManagerService.class);                
    String portalName = null;
    for(String portalPath: livePortalManagerService.getLivePortalsPath()) {
      if(child.getPath().startsWith(portalPath)) {
        portalName = livePortalManagerService.getPortalNameByPath(portalPath);
        break;
      }      
    }
    if(portalName == null) return null;    
    return livePortalManagerService.getLivePortal(sessionProvider, portalName);
  }
  
  private void createSharedJsNode(Node parentNode) throws Exception {
    Node jsNode;
    jsNode = parentNode.addNode("sharedJsFile.js", "nt:file");
    if (!jsNode.isNodeType("exo:jsFile")) {
      jsNode.addMixin("exo:jsFile");
    }
    jsNode.setProperty("exo:active", true);
    jsNode.setProperty("exo:priority", 2);
    jsNode.setProperty("exo:sharedJS", true);

    Node jsContent;
    try {
      jsContent = jsNode.getNode("jcr:content");
    } catch (Exception ex) {
      jsContent = jsNode.addNode("jcr:content", "nt:resource");
    }
    jsContent.setProperty("jcr:encoding", "UTF-8");
    jsContent.setProperty("jcr:mimeType", "text/javascript");
    jsContent.setProperty("jcr:lastModified", new Date().getTime());
    String jsData = "This is the default.js file.";
    jsContent.setProperty("jcr:data", jsData);
    session.save();
  }
	
	/* (non-Javadoc)
	 * @see junit.framework.TestCase#tearDown()
	 */
	public void tearDown() throws Exception {
		super.tearDown();
		Node sharedPortalNode = (Node) session.getItem("/sites content/live/shared/js");
		NodeIterator nodeIterator = documentNode.getNodes();
		NodeIterator sharedNode = sharedJsNode.getNodes();
		NodeIterator sharedIterator = sharedPortalNode.getNodes();
		while(nodeIterator.hasNext()) {
		    nodeIterator.nextNode().remove();
		}
		while(sharedNode.hasNext()) {
		  sharedNode.nextNode().remove();
		}
		while(sharedIterator.hasNext()) {
		  sharedIterator.nextNode().remove();
		}
		session.save();
	}
}
