/*
 * Created by SharpDevelop.
 * User: EH058
 * Date: 17/09/2014
 * Time: 15:35
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using ikvm.extensions;
using NUnit.Framework;
using java.io;
using java.util;

using org.joda.time;

using be.fgov.ehealth.technicalconnector.tests.utils;

using be.ehealth.business.mycarenetcommons.builders;
using be.ehealth.business.mycarenetcommons.domain;
using be.ehealth.business.mycarenetcommons.mapper;
using be.ehealth.businessconnector.tarification.builder;
using be.ehealth.technicalconnector.config;
using be.ehealth.technicalconnector.exception;
using be.ehealth.technicalconnector.session;
using be.ehealth.technicalconnector.utils;
using be.fgov.ehealth.messageservices.core.v1;
using be.fgov.ehealth.mycarenet.commons.core.v2;
using be.fgov.ehealth.mycarenet.commons.protocol.v2;
using be.fgov.ehealth.standards.kmehr.cd.v1;
using be.fgov.ehealth.standards.kmehr.schema.v1;
using be.fgov.ehealth.technicalconnector.tests.session;
using be.ehealth.technicalconnector.idgenerator;

namespace be.ehealth.businessconnector.tarification.session
{


/**
 * Integration tests for tarification.
 * 
 * @author EH058
 * 
 * @since
 * 
 */
[TestFixture]
public class TarificationIntegrationTest {

    private static HashMap nissProvider = new HashMap();

    private static HashMap nissMatchScenario = new HashMap();

    static object[] testCase =
{
//    new object[] { "100" },
    new object[] { "300" },
    new object[] { "500" },
//    new object[] { "600" },
    new object[] { "900" }
};

    [SetUp]
    public static  void setupsession() {
        SessionInitializer.init(".\\be.ehealth.businessconnector.tarification.test.properties", SupportedLanguages.NET.getAbbreviation());
        HashMap nisss = new HashMap();
        nisss.put(NISSUSECASE1, "45062120753");
        nisss.put(NISSUSECASE2, "60520504868");
        nisss.put(NISSUSECASE3, "86032817437");
        nisss.put(NISSUSECASE4, "13030117521");
        nisss.put(GMDNIHII, "17385467004");
        nisss.put(GMDNISS, "68010102395");
        nisss.put(GMDFIRSTNAME, "Justine");
        nisss.put(GMDLASTNAME, "Carambar");
        nissProvider.put(OA100, nisss);

        nisss = new HashMap();
        nisss.put(NISSUSECASE1, "64032764903");
        nisss.put(NISSUSECASE2, "66021250154");
        nisss.put(NISSUSECASE3, "74042566174");
        nisss.put(NISSUSECASE4, "71010908576");
        nisss.put(GMDNIHII, "10065828004");
        nisss.put(GMDNISS, "68010102395");
        nisss.put(GMDFIRSTNAME, "Justine");
        nisss.put(GMDLASTNAME, "Carambar");
        nissProvider.put(OA300, nisss);

        nisss = new HashMap();
        nisss.put(NISSUSECASE1, "49020508235");
        nisss.put(NISSUSECASE2, "83092618070");
        nisss.put(NISSUSECASE3, "76103012361");
        nisss.put(NISSUSECASE4, "62091405715");
        nisss.put(GMDNIHII, "16582446000");
        nisss.put(GMDNISS, "68010102395");
        nisss.put(GMDFIRSTNAME, "Justine");
        nisss.put(GMDLASTNAME, "Carambar");
        nissProvider.put(OA500, nisss);

        nisss = new HashMap();
        nisss.put(NISSUSECASE1, "59072957042");
        nisss.put(NISSUSECASE2, "83091041227");
        nisss.put(NISSUSECASE3, "49061015930");
        nisss.put(NISSUSECASE4, "82413101990");
        nisss.put(GMDNIHII, "14372133004");
        nisss.put(GMDNISS, "68010102395");
        nisss.put(GMDFIRSTNAME, "Justine");
        nisss.put(GMDLASTNAME, "Carambar");
        nissProvider.put(OA600, nisss);

        nisss = new HashMap();
        nisss.put(NISSUSECASE1, "59011214562");
        nisss.put(NISSUSECASE2, "73061527277");
        nisss.put(NISSUSECASE3, "90012333497");
        nisss.put(NISSUSECASE4, "85110840949");
        nisss.put(GMDNIHII, "15554246004");
        nisss.put(GMDNISS, "58041916130");
        nisss.put(GMDFIRSTNAME, "MATHIEU");
        nisss.put(GMDLASTNAME, "ALAIN");
        nissProvider.put(OA900, nisss);

        nissMatchScenario.put(SCENARIO1, NISSUSECASE1);
        nissMatchScenario.put(SCENARIO2, NISSUSECASE1);
        nissMatchScenario.put(SCENARIO3, NISSUSECASE1);
        nissMatchScenario.put(SCENARIO4, NISSUSECASE1);
        nissMatchScenario.put(SCENARIO5, NISSUSECASE3);
        nissMatchScenario.put(SCENARIO6, NISSUSECASE4);
        nissMatchScenario.put(SCENARIO7, NISSUSECASE1);
        nissMatchScenario.put(SCENARIO8, NISSUSECASE1);
        nissMatchScenario.put(SCENARIO9, NISSUSECASE2);
        nissMatchScenario.put(SCENARI10, NISSUSECASE2);
        nissMatchScenario.put(SCENARI11, NISSUSECASE2);
    }

    [TearDown]
    public static void teardownSession()  {
        Session.getInstance().unloadSession();
    }

    [Test, TestCaseSource("testCase")]
    public void getTarificationScenario1Test(String oa) {
        testSimpleGetTarification(oa, SCENARIO1, new ExpectedResult("130", null));
    }

    [Test, TestCaseSource("testCase")]
    public void getTarificationScenario2Test(String oa) {
        testSimpleGetTarification(oa, SCENARIO2, new ExpectedResult("172", null));
    }

    [Test, TestCaseSource("testCase")]
    public void getTarificationScenario3Test(String oa) {
        testSimpleGetTarification(oa, SCENARIO3, new ExpectedResult("171", null));
    }

    [Test, TestCaseSource("testCase")]
    public void getTarificationScenario4Test(String oa) {
        testSimpleGetTarification(oa, SCENARIO4, true, new ExpectedResult("166", null));
    }

    [Test, TestCaseSource("testCase")]
    public void getTarificationScenario5Test(String oa) {
        testSimpleGetTarification(oa, SCENARIO5, new ExpectedResult("169", null));
    }

    [Test, TestCaseSource("testCase")]
    public void getTarificationScenario6Test(String oa) {
        testSimpleGetTarification(oa, SCENARIO6, new ExpectedResult("170", null));
    }

    [Test, TestCaseSource("testCase")]
    public void getTarificationScenario7Test(String oa) {
        testSimpleGetTarification(oa, SCENARIO7, new ExpectedResult(null, "3"));
    }

    [Test, TestCaseSource("testCase")]
    public void getTarificationScenario8Test(String oa) {
        testSimpleGetTarification(oa, SCENARIO8, new ExpectedResult(null, "3"));
    }

    [Test, TestCaseSource("testCase")]
    public void getTarificationScenario9Test(String oa) {
        testSimpleGetTarification(oa, SCENARIO9, new ExpectedResult(null, "9"));
    }

    [Test, TestCaseSource("testCase")]
    public void getTarificationScenario10Test(String oa) {
        testSimpleGetTarification(oa, SCENARI10, new ExpectedResult(null, "2"));
    }

    [Test, TestCaseSource("testCase")]
    public void getTarificationScenario11Test(String oa) {
        testSimpleGetTarification(oa, SCENARI11, new ExpectedResult(null, "7"));
    }


    private void testSimpleGetTarification(String oa, String scenarioName, ExpectedResult expectedResult)  {
        testSimpleGetTarification(oa, scenarioName, false, expectedResult);
    }

    private void testSimpleGetTarification(String oa, String scenarioName, Boolean isAnticipative, ExpectedResult expectedResult)  {
        RequestBuilder mapper = TarificationRequestBuilderFactory.getRequestObjectBuilder();
        InputStream businessXmlContentStream = ConnectorIOUtils.getResourceAsStream(".\\examples\\request\\" + scenarioName + "Request.xml");
        Result result = replaceVariableTagsWithContent(oa, scenarioName, System.Text.Encoding.UTF8.GetString(ConnectorIOUtils.getBytes(businessXmlContentStream)), isAnticipative);

        // saveFileValue(result.textContent.getBytes(), "c:/javadev/divers/aaa testcase/req/OA" + oa + " " + scenarioName +
        // " request.xml");

        HashMap maps = (HashMap)nissProvider.get(oa);
          String inputReference = IdGeneratorFactory.getIdGenerator("xsid").generateId();    
        TarificationConsultationRequest request = mapper.buildConsultationRequest(getRoutingForNiss((String)maps.get(nissMatchScenario.get(scenarioName))), result.textContent.getBytes(), inputReference);
        request.getCommonInput().setInputReference(result.kmehrId);
        request.getRouting().setReferenceDate(result.time);
//        request.getRouting().getCareReceiver().setMutuality(oa);
        TarificationSessionService session = TarificationSessionServiceFactory.getTarificationSession();
        TarificationConsultationResponse consultTarificationResponse = session.consultTarification(request);

        BlobType detail = consultTarificationResponse.getReturn().getDetail();
        Blob blob = SendRequestMapper.mapBlobTypeToBlob(detail);
        byte[] content = RequestBuilderFactory.getBlobBuilder("invoicing").checkAndRetrieveContent(blob);
        String responseContent = System.Text.Encoding.UTF8.GetString(content);

        testResultValue(expectedResult, oa, scenarioName, content);

    }

    /**
     * @param expectedResult
     * @param content
     */
    private void testResultValue(ExpectedResult expectedResult, String oa, String scenarioName, byte[] content)  {
        MarshallerHelper helper = new MarshallerHelper(typeof(RetrieveTransactionResponse), typeof(RetrieveTransactionResponse));
        RetrieveTransactionResponse commonInputResponse = (RetrieveTransactionResponse)helper.toObject(content);
        String response = helper.toString(commonInputResponse);
        String assertion = "";
        if (expectedResult.JustificationCode == null) {
            for (int i = 0; i<commonInputResponse.getAcknowledge().getErrors().size() ; i++){
                AcknowledgeType acknowledge = commonInputResponse.getAcknowledge();
                ErrorMyCarenetType error = (ErrorMyCarenetType) acknowledge.getErrors().get(i);
                for (int j = 0; j<error.getCds().size() ; j++){
                    CDERRORMYCARENET code = (CDERRORMYCARENET)error.getCds().get(j);
                    if (expectedResult.ErrorCode.Equals(code.getValue())) {
                        assertion = "OK";
                    }
                }
            }
            if (!"OK".Equals(assertion)) {
                assertion = "OA" + oa + "-->" + scenarioName + "--> Wait for error code " + expectedResult.ErrorCode + " but not found in response";
            }
        } else {
            if (commonInputResponse.getAcknowledge().getErrors() == null || commonInputResponse.getAcknowledge().getErrors().size() == 0) {
                for (int i = 0; i<commonInputResponse.getKmehrmessage().getFolders().size() ; i++){
                    FolderType folder = (FolderType)commonInputResponse.getKmehrmessage().getFolders().get(i);
                    for (int j = 0; j<folder.getTransactions().size() ; j++){
                        be.fgov.ehealth.standards.kmehr.schema.v1.TransactionType transaction = (be.fgov.ehealth.standards.kmehr.schema.v1.TransactionType)folder.getTransactions().get(j);
                        for (int k = 0; k<transaction.getItem().size() ; k++){
                            ItemType item = (ItemType) transaction.getItem().get(k);
                            try {
                                CDITEM cdItem = (CDITEM) item.getCds().get(0);
                                ContentType contentType = (ContentType) item.getContents().get(0);
                                CDCONTENT cdContent = (CDCONTENT) contentType.getCds().get(0);
                                if ("justification".Equals(cdItem.getValue()) && expectedResult.JustificationCode.Equals(cdContent.getValue())) {
                                    assertion = "OK";
                                }
                            } catch (Exception e) {
                                assertion = "OA" + oa + "-->" + scenarioName + "--> Wrong value of content";
                            }
                        }
                    }
                }
                if (!"OK".Equals(assertion)) {
                    assertion = "OA" + oa + "-->" + scenarioName + "--> Wait for justification code " + expectedResult.JustificationCode + " but not found in response";
                }
             } else {
                java.util.List errors = commonInputResponse.getAcknowledge().getErrors();
                for (int i =0;i<errors.size();i++) {
                    ErrorMyCarenetType error = (ErrorMyCarenetType)errors.get(i);
                    java.util.List cds = error.getCds();
                    for (int j=0;j < cds.size();j++) {
                        CDERRORMYCARENET code = (CDERRORMYCARENET)cds.get(j);
                        assertion = "Wait for justification code " + expectedResult.JustificationCode + " but receive error " + code.getValue();
                    }
                }
            }
        }
        if (!"OK".Equals(assertion)) {
            Assert.Fail(assertion);
        }
    }

    /**
     * @param patientNiss
     * @param testFileContent
     * @return
     * @throws TechnicalConnectorException
     */
    private Result replaceVariableTagsWithContent(String oa, String scenarioName, String testFileContent, Boolean isAnticipative) {
        org.joda.time.DateTime dateTimeNow = new org.joda.time.DateTime();
        String khmerId = dateTimeNow.toString("YYYYddhhmmssSS");
        testFileContent = testFileContent.replaceAll("\\$\\{currentTimestamp\\}", khmerId);
        if (isAnticipative) {
            dateTimeNow = dateTimeNow.minusMonths(3);
        }
        String date = dateTimeNow.toString("YYYY-MM-dd");
        testFileContent = testFileContent.replaceAll("\\$\\{currentDate\\}", date);
        String time = dateTimeNow.toString("hh:mm:ss");
        testFileContent = testFileContent.replaceAll("\\$\\{currentTime\\}", time);
        testFileContent = testFileContent.replaceAll("\\$\\{nihiiNumber\\}", SessionUtil.getNihii11());
        testFileContent = testFileContent.replaceAll("\\$\\{lastName\\}", SessionUtil.getLastname());
        testFileContent = testFileContent.replaceAll("\\$\\{firstName\\}", SessionUtil.getFirstname());
        testFileContent = testFileContent.replaceAll("\\$\\{niss\\}", SessionUtil.getNiss());
        testFileContent = testFileContent.replaceAll("\\$\\{professionType\\}", ConfigFactory.getConfigValidator().getProperty("main.kmehr.quality"));
        HashMap niss = (HashMap) nissProvider.get(oa);
        testFileContent = testFileContent.replaceAll("\\$\\{patientNiss\\}", (String) niss.get(nissMatchScenario.get(scenarioName)));
        testFileContent = testFileContent.replaceAll("\\$\\{gmd-Nihii\\}", (String) niss.get(GMDNIHII));
        testFileContent = testFileContent.replaceAll("\\$\\{gmd-Niss\\}", (String) niss.get(GMDNISS));
        testFileContent = testFileContent.replaceAll("\\$\\{gmd-FirstName\\}", (String) niss.get(GMDFIRSTNAME));
        testFileContent = testFileContent.replaceAll("\\$\\{gmd-LastName\\}", (String) niss.get(GMDLASTNAME));
        return new Result(testFileContent, khmerId, dateTimeNow);
    }

    // private static Routing getRouting(String oa) {
    // CareReceiverId careReceiver = new CareReceiverId(null);
    // careReceiver.setMutuality(oa);
    // return new Routing(careReceiver, new DateTime());
    // }

    private static Routing getRoutingForNiss(String niss) {
        CareReceiverId careReceiver = new CareReceiverId(niss);
        return new Routing(careReceiver, new org.joda.time.DateTime());
    }

    private static  String SCENARIO1 = "scenario01";

    private static  String SCENARIO2 = "scenario02";

    private static  String SCENARIO3 = "scenario03";

    private static  String SCENARIO4 = "scenario04";

    private static  String SCENARIO5 = "scenario05";

    private static  String SCENARIO6 = "scenario06";

    private static  String SCENARIO7 = "scenario07";

    private static  String SCENARIO8 = "scenario08";

    private static  String SCENARIO9 = "scenario09";

    private static  String SCENARI10 = "scenario10";

    private static  String SCENARI11 = "scenario11";

    private static  String OA100 = "100";

    private static  String OA500 = "500";

    private static  String OA600 = "600";

    private static  String OA900 = "900";

    private static  String OA300 = "300";

    private static  String NISSUSECASE1 = "case1";

    private static  String NISSUSECASE2 = "case2";

    private static  String NISSUSECASE3 = "case3";

    private static  String NISSUSECASE4 = "case4";

    private static  String GMDNIHII = "gmd-Nihii";

    private static  String GMDNISS = "gmd-Niss";

    private static  String GMDFIRSTNAME = "gmd-FirstName";

    private static  String GMDLASTNAME = "gmd-LastName";


    /**
     * 
     * used to get the content xml of the request fullfilled and the kmehr id.
     * 
     * @author EH058
     * 
     */
    private  class Result {

        public String textContent;

        public String kmehrId;

        public org.joda.time.DateTime time;

        /**
         * @param textContent
         * @param kmehrId
         */
        public Result(String textContent, String kmehrId, org.joda.time.DateTime time) {
            this.textContent = textContent;
            this.kmehrId = kmehrId;
            this.time = time;
        }
    }

    /**
     * 
     * use to select the value to verify on the response.
     * 
     * @author EH058
     * 
     * 
     */
    private  class ExpectedResult {

        public String ErrorCode;

        public String JustificationCode;

        /**
         * @param errorCode
         * @param justificationCode
         */
        public ExpectedResult(String errorCode, String justificationCode)  {
            if (errorCode == null && justificationCode == null) {
                throw new Exception("error code = " + errorCode + " justification code = " + justificationCode + " one and only one must be filled");
            }
            ErrorCode = errorCode;
            JustificationCode = justificationCode;
        }


    }
}
    /// <summary>
    /// Description of Class1.
    /// </summary>
    public class Class1
    {
        public Class1()
        {
        }
    }
}
