/*
 * Copyright 2008 the original author or authors.
 * 
 * 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.mockftpserver.fake.command

import org.mockftpserver.core.command.Command
import org.mockftpserver.core.command.CommandHandler
import org.mockftpserver.core.command.ReplyCodes
import org.mockftpserver.core.session.SessionKeys
import org.mockftpserver.core.session.StubSession
import org.mockftpserver.fake.StubServerConfiguration
import org.mockftpserver.fake.UserAccount
import org.mockftpserver.fake.filesystem.DirectoryEntry
import org.mockftpserver.fake.filesystem.FileEntry
import org.mockftpserver.fake.filesystem.FileSystemException
import org.mockftpserver.fake.filesystem.TestUnixFakeFileSystem
import org.mockftpserver.test.AbstractGroovyTestCase
import org.mockftpserver.test.StubResourceBundle

/**
 * Abstract superclass for CommandHandler tests
 *
 * @version $Revision$ - $Date$
 *
 * @author Chris Mair
 */
abstract class AbstractFakeCommandHandlerTestCase extends AbstractGroovyTestCase {

    protected static final ERROR_MESSAGE_KEY = 'msgkey'

    protected session
    protected serverConfiguration
    protected replyTextBundle
    protected commandHandler
    protected fileSystem
    protected userAccount

    /** Set this to false to skip the test that verifies that the CommandHandler requires a logged in user              */
    boolean testNotLoggedIn = true

    //-------------------------------------------------------------------------
    // Tests (common to all subclasses)
    //-------------------------------------------------------------------------

    void testHandleCommand_ServerConfigurationIsNull() {
        commandHandler.serverConfiguration = null
        def command = createValidCommand()
        shouldFailWithMessageContaining("serverConfiguration") { commandHandler.handleCommand(command, session) }
    }

    void testHandleCommand_CommandIsNull() {
        shouldFailWithMessageContaining("command") { commandHandler.handleCommand(null, session) }
    }

    void testHandleCommand_SessionIsNull() {
        def command = createValidCommand()
        shouldFailWithMessageContaining("session") { commandHandler.handleCommand(command, null) }
    }

    void testHandleCommand_NotLoggedIn() {
        if (getProperty('testNotLoggedIn')) {
            def command = createValidCommand()
            session.removeAttribute(SessionKeys.USER_ACCOUNT)
            commandHandler.handleCommand(command, session)
            assertSessionReply(ReplyCodes.NOT_LOGGED_IN)
        }
    }

    //-------------------------------------------------------------------------
    // Abstract Method Declarations (must be implemented by all subclasses)
    //-------------------------------------------------------------------------

    /**
     * Create and return a new instance of the CommandHandler class under test. Concrete subclasses must implement.
     */
    abstract CommandHandler createCommandHandler()

    /**
     * Create and return a valid instance of the Command for the CommandHandler class 
     * under test. Concrete subclasses must implement.
     */
    abstract Command createValidCommand()

    //-------------------------------------------------------------------------
    // Test Setup
    //-------------------------------------------------------------------------

    void setUp() {
        super.setUp()
        session = new StubSession()
        serverConfiguration = new StubServerConfiguration()
        replyTextBundle = new StubResourceBundle()
        fileSystem = new TestUnixFakeFileSystem()
        fileSystem.createParentDirectoriesAutomatically = true
        serverConfiguration.setFileSystem(fileSystem)

        userAccount = new UserAccount()
        session.setAttribute(SessionKeys.USER_ACCOUNT, userAccount)

        commandHandler = createCommandHandler()
        commandHandler.serverConfiguration = serverConfiguration
        commandHandler.replyTextBundle = replyTextBundle
    }

    //-------------------------------------------------------------------------
    // Helper Methods
    //-------------------------------------------------------------------------

    /**
     * Perform a test of the handleCommand() method on the specified command
     * parameters, which are missing a required parameter for this CommandHandler.
     */
    protected void testHandleCommand_MissingRequiredParameter(List commandParameters) {
        commandHandler.handleCommand(createCommand(commandParameters), session)
        assertSessionReply(ReplyCodes.COMMAND_SYNTAX_ERROR)
    }

    /**
     * Perform a test of the handleCommand() method on the specified command
     * parameters, which are missing a required parameter for this CommandHandler.
     */
    protected testHandleCommand_MissingRequiredSessionAttribute() {
        def command = createValidCommand()
        commandHandler.handleCommand(command, session)
        assertSessionReply(ReplyCodes.ILLEGAL_STATE)
    }

    /**
     * @return a new Command with the specified parameters for this CommandHandler
     */
    protected Command createCommand(List commandParameters) {
        new Command(createValidCommand().name, commandParameters)
    }

    /**
     * Invoke the handleCommand() method for the current CommandHandler, passing in
     * the specified parameters
     * @param parameters - the List of command parameters; may be empty, but not null
     */
    protected void handleCommand(List parameters) {
        commandHandler.handleCommand(createCommand(parameters), session)
    }

    /**
     * Assert that the specified reply code and message containing text was sent through the session.
     * @param expectedReplyCode - the expected reply code
     * @param text - the text expected within the reply message; defaults to the reply code as a String
     */
    protected assertSessionReply(int expectedReplyCode, text = expectedReplyCode as String) {
        assertSessionReply(0, expectedReplyCode, text)
    }

    /**
     * Assert that the specified reply code and message containing text was sent through the session.
     * @param replyIndex - the index of the reply to compare
     * @param expectedReplyCode - the expected reply code
     * @param text - the text expected within the reply message; defaults to the reply code as a String
     */
    protected assertSessionReply(int replyIndex, int expectedReplyCode, text = expectedReplyCode as String) {
        LOG.info(session.toString())
        String actualMessage = session.getReplyMessage(replyIndex)
        def actualReplyCode = session.getReplyCode(replyIndex)
        assert actualReplyCode == expectedReplyCode
        if (text instanceof List) {
            text.each { assert actualMessage.contains(it), "[$actualMessage] does not contain [$it]" }
        }
        else {
            assert actualMessage.contains(text), "[$actualMessage] does not contain [$text]"
        }
    }

    /**
     * Assert that the specified reply codes were sent through the session.
     * @param replyCodes - the List of expected sent reply codes
     */
    protected assertSessionReplies(List replyCodes) {
        LOG.info(session.toString())
        replyCodes.eachWithIndex {replyCode, replyIndex ->
            assertSessionReply(replyIndex, replyCode)
        }
    }

    /**
     * Assert that the specified data was sent through the session.
     * @param expectedData - the expected data
     */
    protected assertSessionData(String expectedData) {
        def actual = session.sentData[0]
        assert actual != null, "No data for index [0] sent for $session"
        assert actual == expectedData
    }

    /**
     * Assert that the specified data was sent through the session, terminated by an end-of-line.
     * @param expectedData - the expected data
     */
    protected assertSessionDataWithEndOfLine(String expectedData) {
        assertSessionData(expectedData + endOfLine())
    }

    /**
     * Assert that the data sent through the session terminated with an end-of-line.
     */
    protected assertSessionDataEndsWithEndOfLine() {
        assert session.sentData[0].endsWith(endOfLine())
    }

    /**
     * Execute the handleCommand() method with the specified parameters and 
     * assert that the standard SEND DATA replies were sent through the session.
     * @param parameters - the command parameters to use; defaults to []
     * @param finalReplyCode - the expected final reply code; defaults to ReplyCodes.TRANSFER_DATA_FINAL_OK
     */
    protected handleCommandAndVerifySendDataReplies(parameters = [], int finalReplyCode = ReplyCodes.TRANSFER_DATA_FINAL_OK) {
        handleCommand(parameters)
        assertSessionReplies([ReplyCodes.TRANSFER_DATA_INITIAL_OK, finalReplyCode])
    }

    /**
     * Execute the handleCommand() method with the specified parameters and
     * assert that the standard SEND DATA replies were sent through the session.
     * @param parameters - the command parameters to use
     * @param initialReplyMessageKey - the expected reply message key for the initial reply
     * @param finalReplyMessageKey -  the expected reply message key for the final reply
     * @param finalReplyCode - the expected final reply code; defaults to ReplyCodes.TRANSFER_DATA_FINAL_OK
     */
    protected handleCommandAndVerifySendDataReplies(parameters, String initialReplyMessageKey, String finalReplyMessageKey, int finalReplyCode = ReplyCodes.TRANSFER_DATA_FINAL_OK) {
        handleCommand(parameters)
        assertSessionReply(0, ReplyCodes.TRANSFER_DATA_INITIAL_OK, initialReplyMessageKey)
        assertSessionReply(1, finalReplyCode, finalReplyMessageKey)
    }

    /**
     * Override the named method for the specified object instance
     * @param object - the object instance
     * @param methodName - the name of the method to override
     * @param newMethod - the Closure representing the new method for this single instance
     */
    protected void overrideMethod(object, String methodName, Closure newMethod) {
        LOG.info("Overriding method [$methodName] for class [${object.class}]")
        def emc = new ExpandoMetaClass(object.class, false)
        emc."$methodName" = newMethod
        emc.initialize()
        object.metaClass = emc
    }

    /**
     * Override the named method (that takes a single String arg) of the fileSystem object to throw a (generic) FileSystemException
     * @param methodName - the name of the fileSystem method to override
     */
    protected void overrideMethodToThrowFileSystemException(String methodName) {
        def newMethod = {String path -> throw new FileSystemException("Error thrown by method [$methodName]", ERROR_MESSAGE_KEY) }
        overrideMethod(fileSystem, methodName, newMethod)
    }

    /**
     * Set the current directory within the session
     * @param path - the new path value for the current directory
     */
    protected void setCurrentDirectory(String path) {
        session.setAttribute(SessionKeys.CURRENT_DIRECTORY, path)
    }

    /**
     * Convenience method to return the end-of-line character(s) for the current CommandHandler.
     */
    protected endOfLine() {
        commandHandler.endOfLine()
    }

    /**
     * Create a new directory entry with the specified path in the file system
     * @param path - the path of the new directory entry
     * @return the newly created DirectoryEntry
     */
    protected DirectoryEntry createDirectory(String path) {
        DirectoryEntry entry = new DirectoryEntry(path)
        fileSystem.add(entry)
        return entry
    }

    /**
     * Create a new file entry with the specified path in the file system
     * @param path - the path of the new file entry
     * @param contents - the contents for the file; defaults to null
     * @return the newly created FileEntry
     */
    protected FileEntry createFile(String path, contents = null) {
        FileEntry entry = new FileEntry(path: path, contents: contents)
        fileSystem.add(entry)
        return entry
    }

}