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

package com.twilio.rest.preview.hostedNumbers;

import com.twilio.base.Creator;
import com.twilio.converter.Promoter;
import com.twilio.exception.ApiConnectionException;
import com.twilio.exception.ApiException;
import com.twilio.exception.RestException;
import com.twilio.http.HttpMethod;
import com.twilio.http.Request;
import com.twilio.http.Response;
import com.twilio.http.TwilioRestClient;
import com.twilio.rest.Domains;

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

/**
 * PLEASE NOTE that this class contains preview products that are subject to
 * change. Use them with caution. If you currently do not have developer preview
 * access, please contact help@twilio.com.
 */
public class HostedNumberOrderCreator extends Creator<HostedNumberOrder> {
    private final com.twilio.type.PhoneNumber phoneNumber;
    private final Boolean smsCapability;
    private String accountSid;
    private String friendlyName;
    private String uniqueName;
    private List<String> ccEmails;
    private URI smsUrl;
    private HttpMethod smsMethod;
    private URI smsFallbackUrl;
    private HttpMethod smsFallbackMethod;
    private URI statusCallbackUrl;
    private HttpMethod statusCallbackMethod;
    private String smsApplicationSid;
    private String addressSid;
    private String email;
    private HostedNumberOrder.VerificationType verificationType;
    private String verificationDocumentSid;

    /**
     * Construct a new HostedNumberOrderCreator.
     *
     * @param phoneNumber An E164 formatted phone number.
     * @param smsCapability Specify SMS capability to host.
     */
    public HostedNumberOrderCreator(final com.twilio.type.PhoneNumber phoneNumber,
                                    final Boolean smsCapability) {
        this.phoneNumber = phoneNumber;
        this.smsCapability = smsCapability;
    }

    /**
     * This defaults to the AccountSid of the authorization the user is using. This
     * can be provided to specify a subaccount to add the HostedNumberOrder to..
     *
     * @param accountSid Account Sid.
     * @return this
     */
    public HostedNumberOrderCreator setAccountSid(final String accountSid) {
        this.accountSid = accountSid;
        return this;
    }

    /**
     * A 64 character string that is a human readable text that describes this
     * resource..
     *
     * @param friendlyName A human readable description of this resource.
     * @return this
     */
    public HostedNumberOrderCreator setFriendlyName(final String friendlyName) {
        this.friendlyName = friendlyName;
        return this;
    }

    /**
     * Optional. Provides a unique and addressable name to be assigned to this
     * HostedNumberOrder, assigned by the developer, to be optionally used in
     * addition to SID..
     *
     * @param uniqueName A unique, developer assigned name of this
     *                   HostedNumberOrder.
     * @return this
     */
    public HostedNumberOrderCreator setUniqueName(final String uniqueName) {
        this.uniqueName = uniqueName;
        return this;
    }

    /**
     * Optional. A list of emails that the LOA document for this HostedNumberOrder
     * will be carbon copied to..
     *
     * @param ccEmails A list of emails.
     * @return this
     */
    public HostedNumberOrderCreator setCcEmails(final List<String> ccEmails) {
        this.ccEmails = ccEmails;
        return this;
    }

    /**
     * Optional. A list of emails that the LOA document for this HostedNumberOrder
     * will be carbon copied to..
     *
     * @param ccEmails A list of emails.
     * @return this
     */
    public HostedNumberOrderCreator setCcEmails(final String ccEmails) {
        return setCcEmails(Promoter.listOfOne(ccEmails));
    }

    /**
     * The URL that Twilio should request when somebody sends an SMS to the phone
     * number. This will be copied onto the IncomingPhoneNumber resource..
     *
     * @param smsUrl SMS URL.
     * @return this
     */
    public HostedNumberOrderCreator setSmsUrl(final URI smsUrl) {
        this.smsUrl = smsUrl;
        return this;
    }

    /**
     * The URL that Twilio should request when somebody sends an SMS to the phone
     * number. This will be copied onto the IncomingPhoneNumber resource..
     *
     * @param smsUrl SMS URL.
     * @return this
     */
    public HostedNumberOrderCreator setSmsUrl(final String smsUrl) {
        return setSmsUrl(Promoter.uriFromString(smsUrl));
    }

    /**
     * The HTTP method that should be used to request the SmsUrl. Must be either
     * `GET` or `POST`.  This will be copied onto the IncomingPhoneNumber resource..
     *
     * @param smsMethod SMS Method.
     * @return this
     */
    public HostedNumberOrderCreator setSmsMethod(final HttpMethod smsMethod) {
        this.smsMethod = smsMethod;
        return this;
    }

    /**
     * A URL that Twilio will request if an error occurs requesting or executing the
     * TwiML defined by SmsUrl. This will be copied onto the IncomingPhoneNumber
     * resource..
     *
     * @param smsFallbackUrl SMS Fallback URL.
     * @return this
     */
    public HostedNumberOrderCreator setSmsFallbackUrl(final URI smsFallbackUrl) {
        this.smsFallbackUrl = smsFallbackUrl;
        return this;
    }

    /**
     * A URL that Twilio will request if an error occurs requesting or executing the
     * TwiML defined by SmsUrl. This will be copied onto the IncomingPhoneNumber
     * resource..
     *
     * @param smsFallbackUrl SMS Fallback URL.
     * @return this
     */
    public HostedNumberOrderCreator setSmsFallbackUrl(final String smsFallbackUrl) {
        return setSmsFallbackUrl(Promoter.uriFromString(smsFallbackUrl));
    }

    /**
     * The HTTP method that should be used to request the SmsFallbackUrl. Must be
     * either `GET` or `POST`. This will be copied onto the IncomingPhoneNumber
     * resource..
     *
     * @param smsFallbackMethod SMS Fallback Method.
     * @return this
     */
    public HostedNumberOrderCreator setSmsFallbackMethod(final HttpMethod smsFallbackMethod) {
        this.smsFallbackMethod = smsFallbackMethod;
        return this;
    }

    /**
     * Optional. The Status Callback URL attached to the IncomingPhoneNumber
     * resource..
     *
     * @param statusCallbackUrl Status Callback URL.
     * @return this
     */
    public HostedNumberOrderCreator setStatusCallbackUrl(final URI statusCallbackUrl) {
        this.statusCallbackUrl = statusCallbackUrl;
        return this;
    }

    /**
     * Optional. The Status Callback URL attached to the IncomingPhoneNumber
     * resource..
     *
     * @param statusCallbackUrl Status Callback URL.
     * @return this
     */
    public HostedNumberOrderCreator setStatusCallbackUrl(final String statusCallbackUrl) {
        return setStatusCallbackUrl(Promoter.uriFromString(statusCallbackUrl));
    }

    /**
     * Optional. The Status Callback Method attached to the IncomingPhoneNumber
     * resource..
     *
     * @param statusCallbackMethod Status Callback Method.
     * @return this
     */
    public HostedNumberOrderCreator setStatusCallbackMethod(final HttpMethod statusCallbackMethod) {
        this.statusCallbackMethod = statusCallbackMethod;
        return this;
    }

    /**
     * Optional. The 34 character sid of the application Twilio should use to handle
     * SMS messages sent to this number. If a `SmsApplicationSid` is present, Twilio
     * will ignore all of the SMS urls above and use those set on the application..
     *
     * @param smsApplicationSid SMS Application Sid.
     * @return this
     */
    public HostedNumberOrderCreator setSmsApplicationSid(final String smsApplicationSid) {
        this.smsApplicationSid = smsApplicationSid;
        return this;
    }

    /**
     * Optional. A 34 character string that uniquely identifies the Address resource
     * that represents the address of the owner of this phone number..
     *
     * @param addressSid Address sid.
     * @return this
     */
    public HostedNumberOrderCreator setAddressSid(final String addressSid) {
        this.addressSid = addressSid;
        return this;
    }

    /**
     * Optional. Email of the owner of this phone number that is being hosted..
     *
     * @param email Email.
     * @return this
     */
    public HostedNumberOrderCreator setEmail(final String email) {
        this.email = email;
        return this;
    }

    /**
     * Optional. The method used for verifying ownership of the number to be hosted.
     * One of phone-call (default) or phone-bill..
     *
     * @param verificationType Verification Type.
     * @return this
     */
    public HostedNumberOrderCreator setVerificationType(final HostedNumberOrder.VerificationType verificationType) {
        this.verificationType = verificationType;
        return this;
    }

    /**
     * Optional. The unique sid identifier of the Identity Document that represents
     * the document for verifying ownership of the number to be hosted. Required
     * when VerificationType is phone-bill..
     *
     * @param verificationDocumentSid Verification Document Sid
     * @return this
     */
    public HostedNumberOrderCreator setVerificationDocumentSid(final String verificationDocumentSid) {
        this.verificationDocumentSid = verificationDocumentSid;
        return this;
    }

    /**
     * Make the request to the Twilio API to perform the create.
     *
     * @param client TwilioRestClient with which to make the request
     * @return Created HostedNumberOrder
     */
    @Override
    @SuppressWarnings("checkstyle:linelength")
    public HostedNumberOrder create(final TwilioRestClient client) {
        Request request = new Request(
            HttpMethod.POST,
            Domains.PREVIEW.toString(),
            "/HostedNumbers/HostedNumberOrders"
        );

        addPostParams(request);
        Response response = client.request(request);

        if (response == null) {
            throw new ApiConnectionException("HostedNumberOrder creation failed: Unable to connect to server");
        } else if (!TwilioRestClient.SUCCESS.test(response.getStatusCode())) {
            RestException restException = RestException.fromJson(response.getStream(), client.getObjectMapper());
            if (restException == null) {
                throw new ApiException("Server Error, no content");
            }
            throw new ApiException(restException);
        }

        return HostedNumberOrder.fromJson(response.getStream(), client.getObjectMapper());
    }

    /**
     * Add the requested post parameters to the Request.
     *
     * @param request Request to add post params to
     */
    private void addPostParams(final Request request) {
        if (phoneNumber != null) {
            request.addPostParam("PhoneNumber", phoneNumber.toString());
        }

        if (smsCapability != null) {
            request.addPostParam("SmsCapability", smsCapability.toString());
        }

        if (accountSid != null) {
            request.addPostParam("AccountSid", accountSid);
        }

        if (friendlyName != null) {
            request.addPostParam("FriendlyName", friendlyName);
        }

        if (uniqueName != null) {
            request.addPostParam("UniqueName", uniqueName);
        }

        if (ccEmails != null) {
            for (String prop : ccEmails) {
                request.addPostParam("CcEmails", prop);
            }
        }

        if (smsUrl != null) {
            request.addPostParam("SmsUrl", smsUrl.toString());
        }

        if (smsMethod != null) {
            request.addPostParam("SmsMethod", smsMethod.toString());
        }

        if (smsFallbackUrl != null) {
            request.addPostParam("SmsFallbackUrl", smsFallbackUrl.toString());
        }

        if (smsFallbackMethod != null) {
            request.addPostParam("SmsFallbackMethod", smsFallbackMethod.toString());
        }

        if (statusCallbackUrl != null) {
            request.addPostParam("StatusCallbackUrl", statusCallbackUrl.toString());
        }

        if (statusCallbackMethod != null) {
            request.addPostParam("StatusCallbackMethod", statusCallbackMethod.toString());
        }

        if (smsApplicationSid != null) {
            request.addPostParam("SmsApplicationSid", smsApplicationSid);
        }

        if (addressSid != null) {
            request.addPostParam("AddressSid", addressSid);
        }

        if (email != null) {
            request.addPostParam("Email", email);
        }

        if (verificationType != null) {
            request.addPostParam("VerificationType", verificationType.toString());
        }

        if (verificationDocumentSid != null) {
            request.addPostParam("VerificationDocumentSid", verificationDocumentSid);
        }
    }
}