/**
 * This code was generated by
 * \ / _    _  _|   _  _
 *  | (_)\/(_)(_|\/| |(/_  v1.0.0
 *       /       /
 */

package com.twilio.twiml.voice;

import com.twilio.converter.Promoter;
import com.twilio.twiml.GenericNode;
import org.junit.Assert;
import org.junit.Test;

import java.net.URI;
import java.util.List;

/**
 * Test class for {@link Pay}
 */
public class PayTest {
    @Test
    public void testEmptyElement() {
        Pay elem = new Pay.Builder().build();

        Assert.assertEquals(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
            "<Pay/>",
            elem.toXml()
        );
    }

    @Test
    public void testEmptyElementUrl() {
        Pay elem = new Pay.Builder().build();

        Assert.assertEquals("%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%3CPay%2F%3E", elem.toUrl());
    }

    @Test
    public void testElementWithParams() {
        Pay elem = new Pay.Builder()
            .input(Pay.Input.DTMF)
            .action(URI.create("https://example.com"))
            .bankAccountType(Pay.BankAccountType.CONSUMER_CHECKING)
            .statusCallback(URI.create("https://example.com"))
            .statusCallbackMethod(Pay.StatusCallbackMethod.GET)
            .timeout(1)
            .maxAttempts(1)
            .securityCode(true)
            .postalCode("postal_code")
            .minPostalCodeLength(1)
            .paymentConnector("payment_connector")
            .paymentMethod(Pay.PaymentMethod.ACH_DEBIT)
            .tokenType(Pay.TokenType.ONE_TIME)
            .chargeAmount("charge_amount")
            .currency("currency")
            .description("description")
            .validCardTypes(Promoter.listOfOne(Pay.ValidCardTypes.VISA))
            .language(Pay.Language.DE_DE)
            .build();

        Assert.assertEquals(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
            "<Pay action=\"https://example.com\" bankAccountType=\"consumer-checking\" chargeAmount=\"charge_amount\" currency=\"currency\" description=\"description\" input=\"dtmf\" language=\"de-DE\" maxAttempts=\"1\" minPostalCodeLength=\"1\" paymentConnector=\"payment_connector\" paymentMethod=\"ach-debit\" postalCode=\"postal_code\" securityCode=\"true\" statusCallback=\"https://example.com\" statusCallbackMethod=\"GET\" timeout=\"1\" tokenType=\"one-time\" validCardTypes=\"visa\"/>",
            elem.toXml()
        );
    }

    @Test
    public void testElementWithExtraAttributes() {
        Pay elem = new Pay.Builder().option("foo", "bar").option("a", "b").build();

        Assert.assertEquals(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
            "<Pay a=\"b\" foo=\"bar\"/>",
            elem.toXml()
        );
    }

    @Test
    public void testElementWithChildren() {
        Pay.Builder builder = new Pay.Builder();

        builder.prompt(new Prompt.Builder()
                    .for_(Prompt.For.PAYMENT_CARD_NUMBER)
                    .errorTypes(Promoter.listOfOne(Prompt.ErrorType.TIMEOUT))
                    .cardTypes(Promoter.listOfOne(Prompt.CardType.VISA))
                    .attempts(Promoter.listOfOne(1))
                    .build());

        builder.parameter(new Parameter.Builder().name("name").value("value").build());

        Pay elem = builder.build();

        Assert.assertEquals(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
            "<Pay>" +
                "<Prompt attempt=\"1\" cardType=\"visa\" errorType=\"timeout\" for=\"payment-card-number\"/>" +
                "<Parameter name=\"name\" value=\"value\"/>" +
            "</Pay>",
            elem.toXml()
        );
    }

    @Test
    public void testElementWithTextNode() {
        Pay.Builder builder = new Pay.Builder();

        builder.addText("Hey no tags!");

        Pay elem = builder.build();

        Assert.assertEquals(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
            "<Pay>" +
            "Hey no tags!" +
            "</Pay>",
            elem.toXml()
        );
    }

    @Test
    public void testMixedContent() {
        GenericNode.Builder child = new GenericNode.Builder("Child");
        child.addText("content");

        Pay.Builder builder = new Pay.Builder();

        builder.addText("before");
        builder.addChild(child.build());
        builder.addText("after");

        Assert.assertEquals(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
            "<Pay>" +
            "before" +
            "<Child>content</Child>" +
            "after" +
            "</Pay>",
            builder.build().toXml()
        );
    }

    @Test
    public void testElementWithGenericNode() {
        GenericNode.Builder genericBuilder = new GenericNode.Builder("genericTag");
        genericBuilder.addText("Some text");
        GenericNode node = genericBuilder.build();

        Pay.Builder builder = new Pay.Builder();
        Pay elem = builder.addChild(node).build();

        Assert.assertEquals(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
            "<Pay>" +
            "<genericTag>" +
            "Some text" +
            "</genericTag>" +
            "</Pay>",
            elem.toXml()
        );
    }

    @Test
    public void testElementWithGenericNodeAttributes() {
        GenericNode.Builder genericBuilder = new GenericNode.Builder("genericTag");
        GenericNode node = genericBuilder.option("key", "value").addText("someText").build();

        Pay.Builder builder = new Pay.Builder();
        Pay elem = builder.addChild(node).build();

        Assert.assertEquals(
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
            "<Pay>" +
            "<genericTag key=\"value\">" +
            "someText" +
            "</genericTag>" +
            "</Pay>",
            elem.toXml()
        );
    }

    @Test
    public void testXmlAttributesDeserialization() {
        final Pay elem = new Pay.Builder()
            .input(Pay.Input.DTMF)
            .action(URI.create("https://example.com"))
            .bankAccountType(Pay.BankAccountType.CONSUMER_CHECKING)
            .statusCallback(URI.create("https://example.com"))
            .statusCallbackMethod(Pay.StatusCallbackMethod.GET)
            .timeout(1)
            .maxAttempts(1)
            .securityCode(true)
            .postalCode("postal_code")
            .minPostalCodeLength(1)
            .paymentConnector("payment_connector")
            .paymentMethod(Pay.PaymentMethod.ACH_DEBIT)
            .tokenType(Pay.TokenType.ONE_TIME)
            .chargeAmount("charge_amount")
            .currency("currency")
            .description("description")
            .validCardTypes(Promoter.listOfOne(Pay.ValidCardTypes.VISA))
            .language(Pay.Language.DE_DE)
            .build();

        Assert.assertEquals(
            Pay.Builder.fromXml("<Pay action=\"https://example.com\" bankAccountType=\"consumer-checking\" chargeAmount=\"charge_amount\" currency=\"currency\" description=\"description\" input=\"dtmf\" language=\"de-DE\" maxAttempts=\"1\" minPostalCodeLength=\"1\" paymentConnector=\"payment_connector\" paymentMethod=\"ach-debit\" postalCode=\"postal_code\" securityCode=\"true\" statusCallback=\"https://example.com\" statusCallbackMethod=\"GET\" timeout=\"1\" tokenType=\"one-time\" validCardTypes=\"visa\"/>").build().toXml(),
            elem.toXml()
        );
    }

    @Test
    public void testXmlChildrenDeserialization() {
        final Pay.Builder builder = new Pay.Builder();

        builder.prompt(new Prompt.Builder()
                    .for_(Prompt.For.PAYMENT_CARD_NUMBER)
                    .errorTypes(Promoter.listOfOne(Prompt.ErrorType.TIMEOUT))
                    .cardTypes(Promoter.listOfOne(Prompt.CardType.VISA))
                    .attempts(Promoter.listOfOne(1))
                    .build());

        builder.parameter(new Parameter.Builder().name("name").value("value").build());

        final Pay elem = builder.build();

        Assert.assertEquals(
            Pay.Builder.fromXml("<Pay>" +
                "<Prompt attempt=\"1\" cardType=\"visa\" errorType=\"timeout\" for=\"payment-card-number\"/>" +
                "<Parameter name=\"name\" value=\"value\"/>" +
            "</Pay>").build().toXml(),
            elem.toXml()
        );
    }
}