#import <DsUtilities/DsUtilities.h>

#import <DsTrackFramework/GpxExportConfiguration.h>
#import <DsTrackFramework/NamedAndTimedObject.h>

@class NSXMLParser;
@class TrackLibrary;
@class TrackLibraryFolder;
@class TrackPoint;
@class TrackPhoto;
@class TrackKMLConfiguration;

@protocol GISServiceConvertLocation;

#import <DsTrackFramework/PointInTrack.h>

typedef enum
{
    TrackTypeTrack,
    TrackTypeRoute,
    TrackTypePOIs
} TrackTypeType;

@interface Track : NamedAndTimedObject
{
    NSMutableArray* _trackPoints;

    BOOL _isDirty;
    BOOL _propertiesUpdated;
    BOOL _isLoaded;
    BOOL _isSelected;
    BOOL _isHidden;
    NSString* _filename;

    TrackLibraryFolder* _parent;

    double _minElevation;
    double _maxElevation;
    double _minSpeed;
    double _maxSpeed;
    double _length;
    double _ascending;
    double _descending;
    BOOL _hasTimes;
    BOOL _hasElevation;
    NSTimeInterval _durationReal;
    
    int _photoCount;
    int _waypointCount;

    NSColor* _color;

    BOOL _showArea;
    BOOL _showDirectionArrows;
    float _areaDistanceInMeter;
    float _width;
    BOOL _metadataDirty;

    BOOL _timezoneSetDuringImport;

    BOOL _newlyImported;

    NSString* _description;
    NSString* _tags;
    BOOL _syncPhotosOniPhone;

    TrackTypeType _type;

    int _counterGPXExternal;

    BOOL _doNotSaveInStandardLibrary;

    NSString* _trackId;
    NSString* _iCloudId;
    BOOL _iCloudIsUploading;
    NSTimeInterval _iCloudTimestamp;
}

@property (assign, atomic) BOOL doNotSaveInStandardLibrary;
@property (assign, atomic) BOOL newlyImported;
@property (retain, readonly, atomic) NSString* description;
@property (retain, readonly, atomic) NSString* tags;
@property (assign, atomic) BOOL syncPhotosOniPhone;
@property (assign, atomic) TrackTypeType type;
@property (assign, atomic) int waypointCount;
@property (retain, nonatomic) NSString* trackId;
@property (retain, nonatomic) NSString* iCloudId;
@property (assign, atomic) BOOL iCloudIsUploading;
@property (assign, atomic) NSTimeInterval iCloudTimestamp;
@property (assign, atomic) BOOL showDirectionArrows;
@property (assign, atomic) BOOL metadataDirty;

+ (Track*) track;
- (id) init;

+ (Track*) trackWithName:(NSString*)name;
- (id) initWithName:(NSString*)name;

- (void) unload;

- (Track*) clone;

- (void) setTrackPoints:(NSMutableArray*)trackPoints;
- (NSMutableArray*) trackPoints;
- (TrackPoint*) trackPointAtIndex:(NSInteger)index;

- (void) setFilename:(NSString*)filename;
- (NSString*) filename;

- (void) generateNewFilename;

- (void) makeDirty;
- (BOOL) isDirty;
- (void) setIsDirty:(BOOL)newValue;

- (BOOL) isLoaded;
- (void) setIsLoaded:(BOOL)newValue;

- (BOOL) isSelected;
- (void) setIsSelected:(BOOL)newValue;

- (BOOL) isHidden;
- (void) setIsHidden:(BOOL)newValue;

- (BOOL) hasTimes;
- (BOOL) hasElevation;

- (void) addTrackPoint:(TrackPoint*)trackPoint;
- (TrackPoint*) addTrackPointSorted:(TrackPoint*)newTrackPoint;
- (TrackPoint*) addTrackPointNamed:(TrackPoint*)newTrackPoint;
- (void) addTrackPoint:(TrackPoint*)newTrackPoint afterPoint:(TrackPoint*)otherPoint;
- (void) addTrackPoint:(TrackPoint*)newTrackPoint atIndex:(NSInteger)index;
- (void) deleteTrackPoint:(TrackPoint*)trackPoint;
- (void) deleteTrackPoints:(NSIndexSet*)indexset;
- (void) addInterpolatedTrackPointsBetweenFirstIndex:(NSInteger)firstIndex lastIndex:(NSInteger)lastIndex count:(NSInteger)count;

- (void) update;
- (void) updateAll;
- (void) updateTimes;
- (void) updateProperties;

- (double) length;
- (void) setLength:(double)length;
- (void) updateLength;
- (void) updateSpeeds;

- (void) createGPXForParent:(NSXMLElement*)parent waypointsOnly:(BOOL)waypointsOnly configuration:(GpxExportConfiguration*)cfg;

- (BOOL) loadFromLibrary;
- (void) saveToLibrary;
- (void) saveToLibraryWithExternalGPX;

- (void) setName:(NSString*)name;

- (void) removePhotoReferences;
- (void) removeAllWaypoints;

- (TrackPoint*) findTrackPointWithDate:(ISODate*)date;
- (TrackPoint*) findTrackPointBeforeDate:(ISODate*)date;
- (TrackPoint*) findTrackPointAfterDate:(ISODate*)date;
- (TrackPoint*) findTrackPointForCoords:(TrackPoint*)otherTrackPoint;

- (TrackPoint*) firstPoint;
- (TrackPoint*) lastPoint;

- (double) minElevation;
- (double) maxElevation;

- (double) minSpeed;
- (double) maxSpeed;
- (double) averageSpeed;

- (double) ascending;
- (double) descending;

- (void) setPhotoCount:(int)photoCount;
- (int) photoCount;

- (void) calcMinLatitude:(double*)minLatitude MaxLatitude:(double*)maxLatitude MinLongitude:(double*)minLongitude MaxLongitude:(double*)maxLongitude;
- (void) estimateMinLatitude:(double*)minLatitude MaxLatitude:(double*)maxLatitude MinLongitude:(double*)minLongitude MaxLongitude:(double*)maxLongitude;

- (PointInTrack) findNearestPointForLatitude:(double)latitude longitude:(double)longitude nearestPoint:(PointInTrack)nearestPoint;
- (PointInTrack) findNearestPointForLatitude:(double)latitude longitude:(double)longitude;

- (TrackPoint*) previousPoint:(TrackPoint*)segment;
- (TrackPoint*) nextPoint:(TrackPoint*)segment;

- (PointInTrack) firstPointInTrack;
+ (PointInTrack) nextPointInTrack:(PointInTrack)pointInTrack;
+ (PointInTrack) previousPointInTrack:(PointInTrack)pointInTrack;
+ (PointInTrack) nextPointInTrack:(PointInTrack)pointInTrack stepSize:(int)stepSize;
+ (PointInTrack) previousPointInTrack:(PointInTrack)pointInTrack stepSize:(int)stepSize;
+ (PointInTrack) nextWayPointInTrack:(PointInTrack)pointInTrack;
+ (PointInTrack) previousWayPointInTrack:(PointInTrack)pointInTrack;

+ (void) deletePointInTrack:(PointInTrack)pointInTrack;

- (void) setTimezoneOffset:(int)offsetInMinutes;
- (int) timezoneOffset;

- (TrackPhoto*) findFirstPhoto;
- (int) importPhotos:(NSArray*)files maxTimeDiff:(int)maxTimeDiff foundDictionary:(NSMutableDictionary*)foundDictionary;
- (void) addPhotosToBeginningOrEndOfTrack:(NSArray*)files;
- (void) updateExifForGPSLocation:(BOOL)gpsLocation locationInformation:(BOOL)locationInformation addKeywords:(BOOL)addKeywords timeStamps:(BOOL)timeStamps;
- (BOOL) updateAddressInformationWithService:(id<GISServiceConvertLocation>)service;

- (TrackLibraryFolder*) parent;
- (void) setParent:(TrackLibraryFolder*)newValue;
- (NSString*) path;
- (NSString*) folderPath;
- (NSString*) folderPathDisplayString;
- (NSArray*) pathArray;

- (void) addTrackPhotos:(NSMutableArray*)array;

- (NSColor*) color;
- (void) setColor:(NSColor*)newValue;

- (float) width;
- (void) setWidth:(float)width;

- (BOOL) showArea;
- (void) setShowArea:(BOOL)newValue;

- (float) areaDistanceInMeter;
- (void) setAreaDistanceInMeter:(float)newValue;

- (BOOL) isBeforeTrack:(ISODate*)dateOfPhoto;
- (BOOL) isAfterTrack:(ISODate*)dateOfPhoto;

- (BOOL) timezoneSetDuringImport;
- (void) setTimezoneSetDuringImport:(BOOL)newValue;

- (void) checkExistenceOfPhotos;
- (void) stripToAtMostTrackPoints:(int)maxNumberOfTrackPoints;

- (void) setDescription:(NSString*)description;
- (void) setTags:(NSString*)tags;

- (void) setCounterGPXExternal:(int)newValue;
- (int) counterGPXExternal;
- (int) nextIndexForGPXExternalFile;

- (void) toggleiCloud;

- (void) createKMLTrackForParent:(NSXMLElement*)parent configuration:(TrackKMLConfiguration*)configuration;
- (void) createKMLTrackPhotosForParent:(NSXMLElement*)parent relativePath:(NSString*)relativePath kmlRoot:(NSString*)kmlRoot configuration:(TrackKMLConfiguration*)configuration;
- (void) createKMLWaypointsForParent:(NSXMLElement*)parent configuration:(TrackKMLConfiguration*)configuration;

- (BOOL) exportExternalGpx:(NSString*)filename withPhotos:(BOOL)withPhotos additionalFiles:(NSMutableArray*)additionalFiles;
- (void) exportKml:(NSString*)filename withPhotos:(BOOL)withPhotos createKMZ:(BOOL)createKMZ;

- (void) setDurationReal:(NSTimeInterval)value;
- (NSTimeInterval) durationReal;
- (NSString*) durationRealString;

- (void) convertToRoute;
- (void) detectSegments;

@end
