001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.plugins.streetside;
003
004import java.util.Collection;
005import java.util.List;
006import java.util.concurrent.CopyOnWriteArrayList;
007
008import org.openstreetmap.josm.plugins.streetside.model.UserProfile;
009
010/**
011 * Class that stores a sequence of {@link StreetsideAbstractImage} objects.
012 *
013 * @author nokutu
014 * @see StreetsideAbstractImage
015 */
016
017public class StreetsideSequence {
018
019
020  /**
021   * Unique identifier. Used only for {@link StreetsideImage} sequences.
022   */
023  private String id;
024  private UserProfile user;
025
026  private double la;
027  private double lo;
028
029  /**
030   * Epoch time when the sequence was created
031   */
032  private long cd;
033
034  /**
035   * The images in the sequence.
036   */
037  private List<StreetsideAbstractImage> images;
038
039  public StreetsideSequence(String id, Long ca) {
040        this.id = id;
041    cd = ca;
042    images = new CopyOnWriteArrayList<>();
043  }
044
045  public StreetsideSequence(String id, double la, double lo) {
046    this.id = id;
047    this.la = la;
048    this.lo = lo;
049    images = new CopyOnWriteArrayList<>();
050  }
051
052  /**
053   * No argument constructor for StreetsideSequence - necessary for JSON serialization
054   */
055  public StreetsideSequence() {
056          images = new CopyOnWriteArrayList<>();
057  }
058
059  public StreetsideSequence(String id, double la, double lo, long ca) {
060        this.id = id;
061        this.la = la;
062        this.lo = lo;
063        cd = ca;
064        images = new CopyOnWriteArrayList<>();
065}
066
067// TODO: Are all my sequences only set with id values? (no LatLon/Cas?) @rrh
068public StreetsideSequence(String id) {
069        this.id = id;
070        images = new CopyOnWriteArrayList<>();
071}
072
073  /**
074   * Adds a new {@link StreetsideAbstractImage} object to the database.
075   *
076   * @param image The {@link StreetsideAbstractImage} object to be added
077   */
078  public synchronized void add(StreetsideAbstractImage image) {
079    images.add(image);
080    image.setSequence(this);
081  }
082
083  /**
084   * Adds a set of {@link StreetsideAbstractImage} objects to the database.
085   *
086   * @param images The set of {@link StreetsideAbstractImage} objects to be added.
087   */
088  public synchronized void add(Collection<? extends StreetsideAbstractImage> images) {
089    this.images.addAll(images);
090    images.forEach(img -> img.setSequence(this));
091  }
092
093  /**
094   * Returns the next {@link StreetsideAbstractImage} in the sequence of a given
095   * {@link StreetsideAbstractImage} object.
096   *
097   * @param image The {@link StreetsideAbstractImage} object whose next image is
098   * going to be returned.
099   *
100   * @return The next {@link StreetsideAbstractImage} object in the sequence.
101   *
102   * @throws IllegalArgumentException if the given {@link StreetsideAbstractImage} object doesn't belong
103   * the this sequence.
104   */
105  public StreetsideAbstractImage next(StreetsideAbstractImage image) {
106    int i = images.indexOf(image);
107    if (i == -1) {
108      throw new IllegalArgumentException();
109    }
110    if (i == images.size() - 1) {
111      return null;
112    }
113    return images.get(i + 1);
114  }
115
116  /**
117   * Returns the previous {@link StreetsideAbstractImage} in the sequence of a
118   * given {@link StreetsideAbstractImage} object.
119   *
120   * @param image The {@link StreetsideAbstractImage} object whose previous image is
121   * going to be returned.
122   *
123   * @return The previous {@link StreetsideAbstractImage} object in the sequence.
124   *
125   * @throws IllegalArgumentException if the given {@link StreetsideAbstractImage} object doesn't belong
126   * the this sequence.
127   */
128  public StreetsideAbstractImage previous(StreetsideAbstractImage image) {
129    int i = images.indexOf(image);
130    if (i < 0) {
131      throw new IllegalArgumentException();
132    }
133    if (i == 0) {
134      return null;
135    }
136    return images.get(i - 1);
137  }
138
139  /**
140   * Removes a {@link StreetsideAbstractImage} object from the database.
141   *
142   * @param image The {@link StreetsideAbstractImage} object to be removed.
143   */
144  public void remove(StreetsideAbstractImage image) {
145    images.remove(image);
146  }
147
148  /**
149   * @param id the id to set
150   */
151  public void setId(String id) {
152    this.id = id;
153  }
154
155  /**
156   * @return the la
157   */
158  public double getLa() {
159    return la;
160  }
161
162  /**
163   * @param la the la to set
164   */
165  public void setLa(double la) {
166    this.la = la;
167  }
168
169  /**
170   * @return the lo
171   */
172  public double getLo() {
173    return lo;
174  }
175
176  /**
177   * @param lo the lo to set
178   */
179  public void setLo(double lo) {
180    this.lo = lo;
181  }
182
183  /**
184   * Returns the Epoch time when the sequence was captured.
185   *
186   * Negative values mean, no value is set.
187   *
188   * @return A long containing the Epoch time when the sequence was captured.
189   */
190  public long getCd() {
191    return cd;
192  }
193
194  /**
195   * Returns all {@link StreetsideAbstractImage} objects contained by this
196   * object.
197   *
198   * @return A {@link List} object containing all the
199   * {@link StreetsideAbstractImage} objects that are part of the
200   * sequence.
201   */
202  public List<StreetsideAbstractImage> getImages() {
203    return images;
204  }
205
206  /**
207   * Returns the unique identifier of the sequence.
208   *
209   * @return A {@code String} containing the unique identifier of the sequence.
210   * null means that the sequence has been created locally for imported
211   * images.
212   */
213  public String getId() {
214    return id;
215  }
216
217  public UserProfile getUser() {
218        return user;
219  }
220}