001/*
002 *   Copyright 2024 Vonage
003 *
004 *   Licensed under the Apache License, Version 2.0 (the "License");
005 *   you may not use this file except in compliance with the License.
006 *   You may obtain a copy of the License at
007 *
008 *        http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *   Unless required by applicable law or agreed to in writing, software
011 *   distributed under the License is distributed on an "AS IS" BASIS,
012 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *   See the License for the specific language governing permissions and
014 *   limitations under the License.
015 */
016package com.vonage.client.conversations;
017
018import com.fasterxml.jackson.annotation.JsonProperty;
019import com.vonage.client.users.channels.Channel;
020import com.vonage.client.users.channels.Pstn;
021import java.net.URI;
022import java.util.ArrayList;
023import java.util.Arrays;
024import java.util.Collection;
025
026/**
027 * Represents a Conversation (request and response).
028 */
029public class Conversation extends BaseConversation {
030        private ConversationStatus state;
031        private Integer sequenceNumber;
032        private ConversationProperties properties;
033        private Collection<? extends Channel> numbers;
034        private Callback callback;
035
036        protected Conversation() {
037        }
038
039        Conversation(Builder builder) {
040                if ((name = builder.name) != null && (name.length() > 100 || name.trim().isEmpty())) {
041                        throw new IllegalArgumentException("Name must be between 1 and 100 characters.");
042                }
043                if ((displayName = builder.displayName) != null && (displayName.length() > 50 || displayName.trim().isEmpty())) {
044                        throw new IllegalArgumentException("Display name must be between 1 and 50 characters.");
045                }
046                imageUrl = builder.imageUrl;
047                properties = builder.properties;
048                callback = builder.callback;
049                if ((numbers = builder.numbers) != null) {
050                        numbers.forEach(Channel::setTypeField);
051                }
052        }
053
054        /**
055         * The state the conversation is in.
056         *
057         * @return The conversation state as an enum, or {@code null} if unknown.
058         */
059        @JsonProperty("state")
060        public ConversationStatus getState() {
061                return state;
062        }
063
064        /**
065         * The last Event ID in this conversation. This ID can be used to retrieve a specific event.
066         *
067         * @return The last event ID as an integer, or {@code null} if unknown.
068         */
069        @JsonProperty("sequence_number")
070        public Integer getSequenceNumber() {
071                return sequenceNumber;
072        }
073
074        /**
075         * Properties for this conversation.
076         *
077         * @return The conversation properties object, or {@code null} if not applicable.
078         */
079        @JsonProperty("properties")
080        public ConversationProperties getProperties() {
081                return properties;
082        }
083
084        /**
085         * Channels containing the contact numbers for this conversation.
086         * Currently, only {@link Pstn} (Phone) type is supported.
087         *
088         * @return The channels associated with this conversation, or {@code null} if unspecified.
089         */
090        @JsonProperty("numbers")
091        public Collection<? extends Channel> getNumbers() {
092                return numbers;
093        }
094
095        /**
096         * Specifies callback parameters for webhooks.
097         *
098         * @return The callback properties, or {@code null} if unspecified.
099         */
100        @JsonProperty("callback")
101        public Callback getCallback() {
102                return callback;
103        }
104
105        /**
106         * Entry point for constructing an instance of this class.
107         * 
108         * @return A new Builder.
109         */
110        public static Builder builder() {
111                return new Builder();
112        }
113
114        /**
115         * Builder for creating or updating a Conversation. All fields are optional.
116         */
117        public static class Builder {
118                private String name, displayName;
119                private URI imageUrl;
120                private ConversationProperties properties;
121                private Collection<? extends Channel> numbers;
122                private Callback callback;
123        
124                Builder() {}
125
126                /**
127                 * Internal conversation name. Must be unique.
128                 *
129                 * @param name The conversation name.
130                 *
131                 * @return This builder.
132                 */
133                public Builder name(String name) {
134                        this.name = name;
135                        return this;
136                }
137
138                /**
139                 * The public facing name of the conversation.
140                 *
141                 * @param displayName The display name.
142                 *
143                 * @return This builder.
144                 */
145                public Builder displayName(String displayName) {
146                        this.displayName = displayName;
147                        return this;
148                }
149
150                /**
151                 * An image URL that you associate with the conversation.
152                 *
153                 * @param imageUrl The image URL as a string.
154                 *
155                 * @return This builder.
156                 */
157                public Builder imageUrl(String imageUrl) {
158                        this.imageUrl = URI.create(imageUrl);
159                        return this;
160                }
161
162                /**
163                 * Properties for this conversation.
164                 *
165                 * @param properties The conversation properties object.
166                 *
167                 * @return This builder.
168                 */
169                public Builder properties(ConversationProperties properties) {
170                        this.properties = properties;
171                        return this;
172                }
173
174                /**
175                 * Sets the PSTN numbers for this conversation.
176                 *
177                 * @param phoneNumber The telephone or mobile number(s) for this conversation in E.164 format.
178                 *
179                 * @return This builder.
180                 */
181                public Builder phone(String... phoneNumber) {
182                        return numbers(Arrays.stream(phoneNumber).map(Pstn::new).toArray(Channel[]::new));
183                }
184
185                /**
186                 * Channels containing the contact numbers for this conversation.
187                 *
188                 * @param numbers The channels associated with this conversation.
189                 *
190                 * @return This builder.
191                 */
192                Builder numbers(Channel... numbers) {
193                        return numbers(Arrays.asList(numbers));
194                }
195
196                /**
197                 * Channels containing the contact numbers for this conversation.
198                 *
199                 * @param numbers The channels associated with this conversation.
200                 *
201                 * @return This builder.
202                 */
203                Builder numbers(Collection<? extends Channel> numbers) {
204                        this.numbers = new ArrayList<>(numbers);
205                        return this;
206                }
207
208                /**
209                 * Specifies callback parameters for webhooks.
210                 *
211                 * @param callback The callback properties, or {@code null} if unspecified.
212                 *
213                 * @return This builder.
214                 */
215                public Builder callback(Callback callback) {
216                        this.callback = callback;
217                        return this;
218                }
219
220                /**
221                 * Builds the {@linkplain Conversation}.
222                 *
223                 * @return An instance of Conversation, populated with all fields from this builder.
224                 */
225                public Conversation build() {
226                        return new Conversation(this);
227                }
228        }
229}