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

package com.twilio.rest.insights.v1;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.twilio.base.Resource;
import com.twilio.converter.Converter;
import com.twilio.converter.DateConverter;
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 lombok.ToString;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@JsonIgnoreProperties(ignoreUnknown = true)
@ToString
public class Conference extends Resource {
    private static final long serialVersionUID = 37768258321037L;

    public enum ConferenceStatus {
        IN_PROGRESS("in_progress"),
        NOT_STARTED("not_started"),
        COMPLETED("completed"),
        SUMMARY_TIMEOUT("summary_timeout");

        private final String value;

        private ConferenceStatus(final String value) {
            this.value = value;
        }

        public String toString() {
            return value;
        }

        /**
         * Generate a ConferenceStatus from a string.
         * @param value string value
         * @return generated ConferenceStatus
         */
        @JsonCreator
        public static ConferenceStatus forValue(final String value) {
            return Promoter.enumFromString(value, ConferenceStatus.values());
        }
    }

    public enum ConferenceEndReason {
        LAST_PARTICIPANT_LEFT("last_participant_left"),
        CONFERENCE_ENDED_VIA_API("conference_ended_via_api"),
        PARTICIPANT_WITH_END_CONFERENCE_ON_EXIT_LEFT("participant_with_end_conference_on_exit_left"),
        LAST_PARTICIPANT_KICKED("last_participant_kicked"),
        PARTICIPANT_WITH_END_CONFERENCE_ON_EXIT_KICKED("participant_with_end_conference_on_exit_kicked");

        private final String value;

        private ConferenceEndReason(final String value) {
            this.value = value;
        }

        public String toString() {
            return value;
        }

        /**
         * Generate a ConferenceEndReason from a string.
         * @param value string value
         * @return generated ConferenceEndReason
         */
        @JsonCreator
        public static ConferenceEndReason forValue(final String value) {
            return Promoter.enumFromString(value, ConferenceEndReason.values());
        }
    }

    public enum Region {
        US1("us1"),
        AU1("au1"),
        BR1("br1"),
        IE1("ie1"),
        JP1("jp1"),
        SG1("sg1"),
        DE1("de1");

        private final String value;

        private Region(final String value) {
            this.value = value;
        }

        public String toString() {
            return value;
        }

        /**
         * Generate a Region from a string.
         * @param value string value
         * @return generated Region
         */
        @JsonCreator
        public static Region forValue(final String value) {
            return Promoter.enumFromString(value, Region.values());
        }
    }

    public enum Tag {
        INVALID_REQUESTED_REGION("invalid_requested_region"),
        DUPLICATE_IDENTITY("duplicate_identity"),
        START_FAILURE("start_failure"),
        REGION_CONFIGURATION_ISSUES("region_configuration_issues"),
        QUALITY_WARNINGS("quality_warnings"),
        PARTICIPANT_BEHAVIOR_ISSUES("participant_behavior_issues"),
        HIGH_PACKET_LOSS("high_packet_loss"),
        HIGH_JITTER("high_jitter"),
        HIGH_LATENCY("high_latency"),
        LOW_MOS("low_mos"),
        DETECTED_SILENCE("detected_silence");

        private final String value;

        private Tag(final String value) {
            this.value = value;
        }

        public String toString() {
            return value;
        }

        /**
         * Generate a Tag from a string.
         * @param value string value
         * @return generated Tag
         */
        @JsonCreator
        public static Tag forValue(final String value) {
            return Promoter.enumFromString(value, Tag.values());
        }
    }

    public enum ProcessingState {
        COMPLETE("complete"),
        IN_PROGRESS("in_progress"),
        TIMEOUT("timeout");

        private final String value;

        private ProcessingState(final String value) {
            this.value = value;
        }

        public String toString() {
            return value;
        }

        /**
         * Generate a ProcessingState from a string.
         * @param value string value
         * @return generated ProcessingState
         */
        @JsonCreator
        public static ProcessingState forValue(final String value) {
            return Promoter.enumFromString(value, ProcessingState.values());
        }
    }

    /**
     * Create a ConferenceFetcher to execute fetch.
     *
     * @param pathConferenceSid Conference SID.
     * @return ConferenceFetcher capable of executing the fetch
     */
    public static ConferenceFetcher fetcher(final String pathConferenceSid) {
        return new ConferenceFetcher(pathConferenceSid);
    }

    /**
     * Create a ConferenceReader to execute read.
     *
     * @return ConferenceReader capable of executing the read
     */
    public static ConferenceReader reader() {
        return new ConferenceReader();
    }

    /**
     * Converts a JSON String into a Conference object using the provided
     * ObjectMapper.
     *
     * @param json Raw JSON String
     * @param objectMapper Jackson ObjectMapper
     * @return Conference object represented by the provided JSON
     */
    public static Conference fromJson(final String json, final ObjectMapper objectMapper) {
        // Convert all checked exceptions to Runtime
        try {
            return objectMapper.readValue(json, Conference.class);
        } catch (final JsonMappingException | JsonParseException e) {
            throw new ApiException(e.getMessage(), e);
        } catch (final IOException e) {
            throw new ApiConnectionException(e.getMessage(), e);
        }
    }

    /**
     * Converts a JSON InputStream into a Conference object using the provided
     * ObjectMapper.
     *
     * @param json Raw JSON InputStream
     * @param objectMapper Jackson ObjectMapper
     * @return Conference object represented by the provided JSON
     */
    public static Conference fromJson(final InputStream json, final ObjectMapper objectMapper) {
        // Convert all checked exceptions to Runtime
        try {
            return objectMapper.readValue(json, Conference.class);
        } catch (final JsonMappingException | JsonParseException e) {
            throw new ApiException(e.getMessage(), e);
        } catch (final IOException e) {
            throw new ApiConnectionException(e.getMessage(), e);
        }
    }

    private final String conferenceSid;
    private final String accountSid;
    private final String friendlyName;
    private final ZonedDateTime createTime;
    private final ZonedDateTime startTime;
    private final ZonedDateTime endTime;
    private final Integer durationSeconds;
    private final Integer connectDurationSeconds;
    private final Conference.ConferenceStatus status;
    private final Integer maxParticipants;
    private final Integer maxConcurrentParticipants;
    private final Integer uniqueParticipants;
    private final Conference.ConferenceEndReason endReason;
    private final String endedBy;
    private final Conference.Region mixerRegion;
    private final Conference.Region mixerRegionRequested;
    private final Boolean recordingEnabled;
    private final Map<String, Object> detectedIssues;
    private final List<Conference.Tag> tags;
    private final Map<String, Object> tagInfo;
    private final Conference.ProcessingState processingState;
    private final URI url;
    private final Map<String, String> links;

    @JsonCreator
    private Conference(@JsonProperty("conference_sid")
                       final String conferenceSid,
                       @JsonProperty("account_sid")
                       final String accountSid,
                       @JsonProperty("friendly_name")
                       final String friendlyName,
                       @JsonProperty("create_time")
                       final String createTime,
                       @JsonProperty("start_time")
                       final String startTime,
                       @JsonProperty("end_time")
                       final String endTime,
                       @JsonProperty("duration_seconds")
                       final Integer durationSeconds,
                       @JsonProperty("connect_duration_seconds")
                       final Integer connectDurationSeconds,
                       @JsonProperty("status")
                       final Conference.ConferenceStatus status,
                       @JsonProperty("max_participants")
                       final Integer maxParticipants,
                       @JsonProperty("max_concurrent_participants")
                       final Integer maxConcurrentParticipants,
                       @JsonProperty("unique_participants")
                       final Integer uniqueParticipants,
                       @JsonProperty("end_reason")
                       final Conference.ConferenceEndReason endReason,
                       @JsonProperty("ended_by")
                       final String endedBy,
                       @JsonProperty("mixer_region")
                       final Conference.Region mixerRegion,
                       @JsonProperty("mixer_region_requested")
                       final Conference.Region mixerRegionRequested,
                       @JsonProperty("recording_enabled")
                       final Boolean recordingEnabled,
                       @JsonProperty("detected_issues")
                       final Map<String, Object> detectedIssues,
                       @JsonProperty("tags")
                       final List<Conference.Tag> tags,
                       @JsonProperty("tag_info")
                       final Map<String, Object> tagInfo,
                       @JsonProperty("processing_state")
                       final Conference.ProcessingState processingState,
                       @JsonProperty("url")
                       final URI url,
                       @JsonProperty("links")
                       final Map<String, String> links) {
        this.conferenceSid = conferenceSid;
        this.accountSid = accountSid;
        this.friendlyName = friendlyName;
        this.createTime = DateConverter.iso8601DateTimeFromString(createTime);
        this.startTime = DateConverter.iso8601DateTimeFromString(startTime);
        this.endTime = DateConverter.iso8601DateTimeFromString(endTime);
        this.durationSeconds = durationSeconds;
        this.connectDurationSeconds = connectDurationSeconds;
        this.status = status;
        this.maxParticipants = maxParticipants;
        this.maxConcurrentParticipants = maxConcurrentParticipants;
        this.uniqueParticipants = uniqueParticipants;
        this.endReason = endReason;
        this.endedBy = endedBy;
        this.mixerRegion = mixerRegion;
        this.mixerRegionRequested = mixerRegionRequested;
        this.recordingEnabled = recordingEnabled;
        this.detectedIssues = detectedIssues;
        this.tags = tags;
        this.tagInfo = tagInfo;
        this.processingState = processingState;
        this.url = url;
        this.links = links;
    }

    /**
     * Returns Conference SID..
     *
     * @return Conference SID.
     */
    public final String getConferenceSid() {
        return this.conferenceSid;
    }

    /**
     * Returns Account SID..
     *
     * @return Account SID.
     */
    public final String getAccountSid() {
        return this.accountSid;
    }

    /**
     * Returns Custom label for the conference..
     *
     * @return Custom label for the conference.
     */
    public final String getFriendlyName() {
        return this.friendlyName;
    }

    /**
     * Returns Conference creation date/time..
     *
     * @return Conference creation date/time.
     */
    public final ZonedDateTime getCreateTime() {
        return this.createTime;
    }

    /**
     * Returns Timestamp in ISO 8601 format when the conference started..
     *
     * @return Timestamp in ISO 8601 format when the conference started.
     */
    public final ZonedDateTime getStartTime() {
        return this.startTime;
    }

    /**
     * Returns Conference end date/time..
     *
     * @return Conference end date/time.
     */
    public final ZonedDateTime getEndTime() {
        return this.endTime;
    }

    /**
     * Returns Conference duration in seconds..
     *
     * @return Conference duration in seconds.
     */
    public final Integer getDurationSeconds() {
        return this.durationSeconds;
    }

    /**
     * Returns Duration of the conference in seconds..
     *
     * @return Duration of the conference in seconds.
     */
    public final Integer getConnectDurationSeconds() {
        return this.connectDurationSeconds;
    }

    /**
     * Returns Status of conference.
     *
     * @return Status of conference
     */
    public final Conference.ConferenceStatus getStatus() {
        return this.status;
    }

    /**
     * Returns Max participants specified in config..
     *
     * @return Max participants specified in config.
     */
    public final Integer getMaxParticipants() {
        return this.maxParticipants;
    }

    /**
     * Returns Actual maximum concurrent participants..
     *
     * @return Actual maximum concurrent participants.
     */
    public final Integer getMaxConcurrentParticipants() {
        return this.maxConcurrentParticipants;
    }

    /**
     * Returns Unique conference participants..
     *
     * @return Unique conference participants.
     */
    public final Integer getUniqueParticipants() {
        return this.uniqueParticipants;
    }

    /**
     * Returns Conference end reason..
     *
     * @return Conference end reason.
     */
    public final Conference.ConferenceEndReason getEndReason() {
        return this.endReason;
    }

    /**
     * Returns Call SID that ended the conference..
     *
     * @return Call SID that ended the conference.
     */
    public final String getEndedBy() {
        return this.endedBy;
    }

    /**
     * Returns Region where the conference was mixed..
     *
     * @return Region where the conference was mixed.
     */
    public final Conference.Region getMixerRegion() {
        return this.mixerRegion;
    }

    /**
     * Returns Configuration-requested conference mixer region..
     *
     * @return Configuration-requested conference mixer region.
     */
    public final Conference.Region getMixerRegionRequested() {
        return this.mixerRegionRequested;
    }

    /**
     * Returns Boolean. Indicates whether recording was enabled..
     *
     * @return Boolean. Indicates whether recording was enabled.
     */
    public final Boolean getRecordingEnabled() {
        return this.recordingEnabled;
    }

    /**
     * Returns Potential issues detected during the conference..
     *
     * @return Potential issues detected during the conference.
     */
    public final Map<String, Object> getDetectedIssues() {
        return this.detectedIssues;
    }

    /**
     * Returns Tags for detected conference conditions and participant behaviors..
     *
     * @return Tags for detected conference conditions and participant behaviors.
     */
    public final List<Conference.Tag> getTags() {
        return this.tags;
    }

    /**
     * Returns Object. Contains details about conference tags..
     *
     * @return Object. Contains details about conference tags.
     */
    public final Map<String, Object> getTagInfo() {
        return this.tagInfo;
    }

    /**
     * Returns Processing state for the Conference Summary resource..
     *
     * @return Processing state for the Conference Summary resource.
     */
    public final Conference.ProcessingState getProcessingState() {
        return this.processingState;
    }

    /**
     * Returns The URL of this resource..
     *
     * @return The URL of this resource.
     */
    public final URI getUrl() {
        return this.url;
    }

    /**
     * Returns Nested resource URLs..
     *
     * @return Nested resource URLs.
     */
    public final Map<String, String> getLinks() {
        return this.links;
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }

        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        Conference other = (Conference) o;

        return Objects.equals(conferenceSid, other.conferenceSid) &&
               Objects.equals(accountSid, other.accountSid) &&
               Objects.equals(friendlyName, other.friendlyName) &&
               Objects.equals(createTime, other.createTime) &&
               Objects.equals(startTime, other.startTime) &&
               Objects.equals(endTime, other.endTime) &&
               Objects.equals(durationSeconds, other.durationSeconds) &&
               Objects.equals(connectDurationSeconds, other.connectDurationSeconds) &&
               Objects.equals(status, other.status) &&
               Objects.equals(maxParticipants, other.maxParticipants) &&
               Objects.equals(maxConcurrentParticipants, other.maxConcurrentParticipants) &&
               Objects.equals(uniqueParticipants, other.uniqueParticipants) &&
               Objects.equals(endReason, other.endReason) &&
               Objects.equals(endedBy, other.endedBy) &&
               Objects.equals(mixerRegion, other.mixerRegion) &&
               Objects.equals(mixerRegionRequested, other.mixerRegionRequested) &&
               Objects.equals(recordingEnabled, other.recordingEnabled) &&
               Objects.equals(detectedIssues, other.detectedIssues) &&
               Objects.equals(tags, other.tags) &&
               Objects.equals(tagInfo, other.tagInfo) &&
               Objects.equals(processingState, other.processingState) &&
               Objects.equals(url, other.url) &&
               Objects.equals(links, other.links);
    }

    @Override
    public int hashCode() {
        return Objects.hash(conferenceSid,
                            accountSid,
                            friendlyName,
                            createTime,
                            startTime,
                            endTime,
                            durationSeconds,
                            connectDurationSeconds,
                            status,
                            maxParticipants,
                            maxConcurrentParticipants,
                            uniqueParticipants,
                            endReason,
                            endedBy,
                            mixerRegion,
                            mixerRegionRequested,
                            recordingEnabled,
                            detectedIssues,
                            tags,
                            tagInfo,
                            processingState,
                            url,
                            links);
    }
}