package com.workfusion.odf.test;

import java.io.IOException;
import java.util.Map;
import javax.inject.Named;

import groovy.lang.Binding;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFilenameFilter;
import org.codejargon.feather.Provides;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.workfusion.odf.core.Intake;
import com.workfusion.odf.core.Module;
import com.workfusion.odf.impl.connector.ShareFolderTransactionSupplier;
import com.workfusion.odf.impl.connector.SmbFileBuilder;
import com.workfusion.rpa.core.storage.S3Manager;

/**
 * Share Folder Connector Bot Configuration xml test supplier.
 *
 * @author Andrei Urbanovich
 */
public class ShareFolderConnectorBotConfigTestSupplier {
	private static final String TEST_SMB_ALIAS = "smbuser";
	private static final String TEST_SMB_FILTER = "*";
	private static final String TEST_SMB_HOST = "localhost";

	private static final String TEST_FILE_1 = "presentation.pdf";
	private static final String TEST_FILE_1_PATH = ShareFolderTransactionSupplier.SMB_PROTOCOL + TEST_SMB_HOST + "/" + TEST_FILE_1;
	// ---
	private static final String TEST_FILE_2 = "TODO.txt";
	private static final String TEST_FILE_2_PATH = ShareFolderTransactionSupplier.SMB_PROTOCOL + TEST_SMB_HOST + "/" + TEST_FILE_2;
	// ---
	private static final String TEST_FOLDER_1 = "folder1";
	private static final String TEST_FOLDER_1_PATH = ShareFolderTransactionSupplier.SMB_PROTOCOL + TEST_SMB_HOST + "/" + TEST_FOLDER_1;
	// ---
	private static final String TEST_FOLDER_1_FILE_1 = "scan1.png";
	private static final String TEST_FOLDER_1_FILE_1_PATH = ShareFolderTransactionSupplier.SMB_PROTOCOL + TEST_SMB_HOST + "/" + TEST_FOLDER_1 + "/" + TEST_FOLDER_1_FILE_1;

    private SmbFileBuilder smbFileBuilder;

    private S3Manager s3Manager;

    private Logger logger;

    private Binding binding;

    private Map<String, String> params;

    /**
     * Default constructor.
     */
    public ShareFolderConnectorBotConfigTestSupplier() {
    	// nope
    }

    public void init() throws Exception {
	    SmbFile smbFile1Mock = mockFile1();
	    SmbFile smbFile2Mock = mockFile2();
	    SmbFile smbFile3Mock = mockFile3();
	    SmbFile smbFolder1Mock = mockFolder1(smbFile3Mock);
		SmbFile smbHomeDirMock = mockSmbHomeDir(smbFile1Mock, smbFile2Mock, smbFolder1Mock);

    	s3Manager = Mockito.mock(S3Manager.class);
    	Mockito.when(s3Manager.putFile(ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any())).thenReturn("s3-file.ext");

        logger = LoggerFactory.getLogger(ShareFolderTransactionSupplier.class);

        smbFileBuilder = Mockito.mock(SmbFileBuilder.class);
        Mockito.when(smbFileBuilder.buildSmbFileByPath(ArgumentMatchers.eq(ShareFolderTransactionSupplier.SMB_PROTOCOL + TEST_SMB_HOST + "/"))).thenReturn(smbHomeDirMock);

        binding = Mockito.mock(Binding.class);

        params = Mockito.mock(Map.class);
        Mockito.when(params.get(ShareFolderTransactionSupplier.PARAM_HOST)).thenReturn(TEST_SMB_HOST);
        Mockito.when(params.get(ShareFolderTransactionSupplier.PARAM_PATH)).thenReturn("/");
        Mockito.when(params.get(ShareFolderTransactionSupplier.PARAM_ALIAS)).thenReturn(TEST_SMB_ALIAS);
        Mockito.when(params.get(ShareFolderTransactionSupplier.PARAM_WILDCARD)).thenReturn(TEST_SMB_FILTER);

        Module testModule = new Module() {
            @Provides
            public S3Manager s3Manager() {
                return s3Manager;
            }

            @Provides
            public Logger logger() {
                return logger;
            }

            @Provides
            public SmbFileBuilder smbFileBuilder() {
                return smbFileBuilder;
            }

            @Provides
            @Named("botConfigParams")
            public Map<String, String> params() {
                return params;
            }
        };

        Intake.init(binding).params(params).override(testModule).injectFields(this).get();
//      def transactions = Intake.init(binding).params(params).get().loadTransactions(ShareFolderTransactionSupplier.class);
    }

	/**
	 * Mock for SMB file #1 (1-st level file).
	 *
	 * @throws IOException
	 */
    private SmbFile mockFile1() throws IOException {
        SmbFile smbFile1Mock = Mockito.mock(SmbFile.class);
        Mockito.when(smbFile1Mock.isDirectory()).thenReturn(Boolean.FALSE);
        Mockito.when(smbFile1Mock.isFile()).thenReturn(Boolean.TRUE);
        Mockito.when(smbFile1Mock.getInputStream()).thenReturn(null);
        Mockito.when(smbFile1Mock.getName()).thenReturn(TEST_FILE_1);
        Mockito.when(smbFile1Mock.getPath()).thenReturn(TEST_FILE_1_PATH);

        return smbFile1Mock;
    }

	/**
	 * Mock for SMB file #2 (1-st level file).
	 *
	 * @throws IOException
	 */
    private SmbFile mockFile2() throws IOException {
        SmbFile smbFile2Mock = Mockito.mock(SmbFile.class);
        Mockito.when(smbFile2Mock.isDirectory()).thenReturn(Boolean.FALSE);
        Mockito.when(smbFile2Mock.isFile()).thenReturn(Boolean.TRUE);
        Mockito.when(smbFile2Mock.getInputStream()).thenReturn(null);
        Mockito.when(smbFile2Mock.getName()).thenReturn(TEST_FILE_2);
        Mockito.when(smbFile2Mock.getPath()).thenReturn(TEST_FILE_2_PATH);

        return smbFile2Mock;
    }

	/**
	 * Mock for SMB file #3 (2-nd level file).
	 *
	 * @throws IOException
	 */
    private SmbFile mockFile3() throws IOException {
        SmbFile smbFile3Mock = Mockito.mock(SmbFile.class);
        Mockito.when(smbFile3Mock.isDirectory()).thenReturn(Boolean.FALSE);
        Mockito.when(smbFile3Mock.isFile()).thenReturn(Boolean.TRUE);
        Mockito.when(smbFile3Mock.getInputStream()).thenReturn(null);
        Mockito.when(smbFile3Mock.getName()).thenReturn(TEST_FOLDER_1_FILE_1);
        Mockito.when(smbFile3Mock.getPath()).thenReturn(TEST_FOLDER_1_FILE_1_PATH);

        return smbFile3Mock;
    }

	/**
	 * Mock for SMB folder #1 (1-st level folder).
	 *
	 * @throws IOException
	 */
    private SmbFile mockFolder1(final SmbFile folderFile) throws IOException {
        SmbFile smbFolder1Mock = Mockito.mock(SmbFile.class);
        Mockito.when(smbFolder1Mock.isDirectory()).thenReturn(Boolean.TRUE);
        Mockito.when(smbFolder1Mock.isFile()).thenReturn(Boolean.FALSE);
        Mockito.when(smbFolder1Mock.getInputStream()).thenReturn(null);
        Mockito.when(smbFolder1Mock.getName()).thenReturn(TEST_FOLDER_1);
        Mockito.when(smbFolder1Mock.getPath()).thenReturn(TEST_FOLDER_1_PATH);
        Mockito.when(smbFolder1Mock.listFiles()).thenReturn(new SmbFile[] {folderFile});

        return smbFolder1Mock;
    }

    private SmbFile mockSmbHomeDir(SmbFile... homeDirFiles) throws IOException {
        SmbFile smbHomeDirMock = Mockito.mock(SmbFile.class);
        Mockito.when(smbHomeDirMock.listFiles(ArgumentMatchers.any(SmbFilenameFilter.class))).thenReturn(homeDirFiles);
        Mockito.when(smbHomeDirMock.listFiles()).thenReturn(homeDirFiles);
        return smbHomeDirMock;
    }
}
