001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package net.tridentsdk.meta;
019
020import com.google.gson.Gson;
021import com.google.gson.JsonArray;
022import com.google.gson.JsonObject;
023import net.tridentsdk.entity.living.Player;
024
025import javax.annotation.concurrent.NotThreadSafe;
026
027/**
028 * Builds a formatted message using JSON to be sent to the player(s)
029 *
030 * @author The TridentSDK Team
031 * @since 0.3-alpha-DP
032 */
033// FIXME
034@NotThreadSafe
035public final class MessageBuilder {
036    static final Gson GSON = new Gson();
037
038    private final JsonObject obj;
039    private final JsonArray extra;
040    private Message buildingObject;
041
042    /**
043     * Starts off with the text of the message
044     *
045     * @param message the text to send
046     */
047    public MessageBuilder(String message) {
048        this.obj = new JsonObject();
049        this.extra = new JsonArray();
050
051        // setup required properties
052        this.obj.addProperty("text", "");
053        this.buildingObject = new Message().text(message);
054    }
055
056    /**
057     * Sets the text color of the message
058     *
059     * @param color the color the message should be
060     * @return the instance of this message builder
061     */
062    public MessageBuilder color(ChatColor color) {
063        this.buildingObject.color(color);
064        return this;
065    }
066
067    /**
068     * Makes the message a clickable link
069     *
070     * @param url the URL to lead the player to when the message is clicked
071     * @return the instance of this message builder
072     */
073    public MessageBuilder link(String url) {
074        this.buildingObject.clickEvent(new ClickEvent().action(ClickEvent.ClickAction.OPEN_URL).value(url));
075
076        return this;
077    }
078
079    /**
080     * Makes the message a clickable link that opens a file on the player's client
081     *
082     * @param file the file to open, must be available on the client
083     * @return the instance of this message builder
084     */
085    public MessageBuilder file(String file) {
086        this.buildingObject.clickEvent(new ClickEvent().action(ClickEvent.ClickAction.OPEN_FILE).value(file));
087
088        return this;
089    }
090
091    /**
092     * Causes a popup to open when the the message is hovered over
093     *
094     * @param message the message in the popup
095     * @return the instance of this message builder
096     */
097    public MessageBuilder hover(String message) {
098        this.buildingObject.hoverEvent(new HoverEvent().action(HoverEvent.HoverAction.SHOW_TEXT).value(message));
099
100        return this;
101    }
102
103    /**
104     * Appends extra text to the end of this message
105     *
106     * @param message the message to be appended after the current text
107     * @return the instance of this message builder
108     */
109    public MessageBuilder then(String message) {
110        this.extra.add(this.buildingObject.message());
111        this.buildingObject = new Message().text(message);
112
113        return this;
114    }
115
116    /**
117     * Appends extra text to the end of this message
118     *
119     * @param message the message to be appended after the current text
120     * @return the instance of this message builder
121     */
122    public MessageBuilder then(Message message) {
123        this.extra.add(this.buildingObject.message());
124        this.buildingObject = message;
125
126        return this;
127    }
128
129    /**
130     * Completes the building of the message, after this call no change should be made. If any change were to be made,
131     * an NPE will be thrown
132     *
133     * @return the finalized MessageBuilder, only {@link #asJson()} and
134     * {@link #sendTo(net.tridentsdk.entity.living.Player...)} may be called on the returned object
135     */
136    public MessageBuilder build() {
137        this.extra.add(buildingObject.message());
138        this.obj.add("extra", this.extra);
139        this.buildingObject = null;
140
141        return this;
142    }
143
144    @Override
145    public String toString() {
146        return GSON.toJson(this.obj);
147    }
148
149    /**
150     * The String format of the JSON to be sent as the formatted text
151     *
152     * @return the String format of the built JSON
153     */
154    public String asJson() {
155        return this.toString();
156    }
157
158    /**
159     * Returns if the {@link #build()} method has been called or not
160     *
161     * @return if the build method has been called or not
162     */
163    public boolean isBuilt() {
164        return buildingObject == null;
165    }
166
167    /**
168     * Sends the formatted text to the specified players
169     *
170     * @param players the players to send the formatted text
171     * @return the instance of this message builder
172     */
173    public MessageBuilder sendTo(Player... players) {
174        for (Player p : players) {
175            p.sendRaw(asJson());
176        }
177
178        return this;
179    }
180}