//
//  BXTracker.h
//  BXTracking
//
//  Created by Alexander Lehnert on 08.01.13.
//  Copyright (c) 2013 Boinx Software Ltd. All rights reserved.
//

#import <Foundation/Foundation.h>

#pragma mark - Error Codes

/*!
 @abstract Predefined Error Code used in (Error**) returns on various places
 */
typedef enum {
    // This error code is returned when input to a method is incorrect.
    kBXTrackerInvalidInputError = 0xbade7a9,
    
    // This error code is returned when the number of hits generated in a session
    // exceeds the limit (currently 500).
    kBXTrackerEventsPerSessionLimitError = 0xbad5704e,
    
    // This error code is returned if the method called requires that the tracker
    // be started.
    kBXTrackerNotStartedError = 0xbada55,
    
    // This error code is returned if the method call resulted in some sort of
    // IO while writing on disk error.
    kBXTrackerIOError = 0xbadbaddb
} BXTrackerErrorCode;


#pragma mark - Constants

/*!
 @var kBXTrackerErrorDomain
 @abstract The error domain for errors originating in the Google Analytics iOS
 SDK. All errors generated by the Google Analytics iOS SDK will belong to
 this domain.
 */
extern NSString* const kBXTrackerErrorDomain;


#pragma mark -

@class BXTracker, BXTrackerQueue;
@protocol BXTrackerDelegate;

#pragma mark -

@interface BXTracker : NSObject {
@private
    // configuration
    BOOL _debug;
    BOOL _dryRun;
    BOOL _anonymizeIp;
    BOOL _isStarted;
    
    // Request related
    NSUInteger _destinationPort;
    NSString *_destinationHost;
    NSString *_destinationPathPrefix;
    
    // basic tracking parameter
    NSString *_accountID;
    NSTimeInterval _dispatchPeriod;
    NSString *_clientUUID;
    
    // Counting
    NSUInteger _hitsPerSession;
    NSUInteger _hitsPerUserDay;
    NSUInteger _hitsFailure;
    
    // callbacks
    id<BXTrackerDelegate> _delegate;
    
    // Timing
    dispatch_source_t _dispatchTimerSource;
    
    // Queueing
    BXTrackerQueue *_queue;
    NSOperationQueue *_operationQueue;
}

@property(nonatomic, readonly) BOOL isStarted;
/*!
 @abstract If true, debug messages will be written to the log.
 This is useful for debugging calls to the Google Analytics SDK.
 By default, this flag is false.
 */
@property(nonatomic, readwrite) BOOL debug;

/*!
 @abstract If true, hits will not be sent to Google Analytics.
 This is useful for debugging calls to the Google Analytics SDK.
 By default, this flag is false.
 */
@property(nonatomic, readwrite) BOOL dryRun;

/*!
 @abstract If true, Google Analytics will anonymize the IP address information
 collected by zeroing out some of the least significant bits of the address. By
 default, this flag is false.
 
 @discussion In the case of IPv4 addresses, the last octet is set to zero. For
 IPv6 addresses, the last 10 octets are set to zero, although this is subject to
 change in the future.
 */
@property(nonatomic, readwrite) BOOL anonymizeIp;

/*!
 @abstract The sampleRate parameter controls the probability that the visitor
 will be sampled. By default, sampleRate is 100, which signifies no sampling.
 sampleRate may be set to any integer value between 0 and 100, inclusive. A
 value of 90 requests 90% of visitors to be sampled (10% of visitors to be
 sampled out).
 
 @discussion When a visitor is not sampled, no data is submitted to Google
 Analytics about that visitor's activity. If your application is subject to
 heavy traffic spikes, you may wish to adjust the sample rate to ensure
 uninterrupted report tracking. Sampling in Google Analytics occurs consistently
 across unique visitors, ensuring integrity in trending and reporting even when
 sampling is enabled, because unique visitors remain included or excluded from
 the sample, as set from the initiation of sampling.
 */
// @property(nonatomic, readwrite) NSUInteger sampleRate;

/*!
 Returns the singleton instance of BXTracker.
 */
+ (BXTracker *)sharedTracker;

/*!
 @abstract Startup the tracker dispatch timer
 
 @param accountID The Google Analytics account ID (the string that begins with
 "UA-").
 
 @param dispatchPeriod The desired automatic dispatch period (in seconds).
 The dispatcher will check for events to dispatch every |dispatchPeriod|
 seconds. If a non-positive (e.g. 0 or -1) dispatch period is given, automatic
 dispatch will not be enabled, and the application will need to dispatch events
 manually using @link dispatch @/link or @link dispatchSynchronous: @/link.
 
 @param delegate An optional delegate which will get notified when hits get
 dispatched.
 */
- (void)startTrackerWithAccountID:(NSString *)accountID
                   dispatchPeriod:(NSTimeInterval)dispatchPeriod
                         delegate:(id<BXTrackerDelegate>)delegate;

/*!
 @abstract Stop the tracker dispatch timer. No events can be processed.
 */
- (void)stopTracker;

/*!
 @abstract Track a page view.
 
 @param pageURL The URL of the pageview to track. A forward-slash ('/')
 character will be prepended to this string if it doesn't start with one.
 
 @param error A location to record the error if one occurs. You may pass 'nil'
 here.
 
 @return YES on success or NO on error.
 */
- (BOOL)trackPageview:(NSString *)pageURL
            withError:(NSError **)error;

/*!
 @abstract Track an event view.
 
 @return YES on success or NO on error.
 
 @param category The event category.
 @param action The event action.
 @param label The event label. This parameter may be nil to indicate no label.
 @param value The event value. This parameter may be -1 to indicate no value.
 @param error A location to record the error if one occurs. You may pass 'nil'
 here.
 */
- (BOOL)trackEvent:(NSString *)category
            action:(NSString *)action
             label:(NSString *)label
             value:(NSInteger)value
         withError:(NSError **)error;

/*!
 @abstract Track an event view.
 
 @return YES on success or NO on error.
 
 @param category The event category.
 */
- (BOOL)trackEvent:(NSString *)category;

/*!
 @abstract Track an event view.
 
 @return YES on success or NO on error.
 
 @param category The event category.
 @param label The event label.
 */
- (BOOL)trackEvent:(NSString *)category
             withLabel:(NSString *)label;

/*!
 @abstract Track an event view.
 
 @return YES on success or NO on error.
 
 @param category The event category.
 @param label The event label.
 @param value The event value. This parameter may be -1 to indicate no value.
 */
- (BOOL)trackEvent:(NSString *)category
			 label:(NSString *)label
		 withValue:(NSInteger)value;

/*!
 @abstract Dispatch pageviews, events, or transactions to Google Analytics.
 
 @discussion Note all event would be dispatched until the queue is empty or
 the max request per session is reached.
 
 @return YES if there were pending pageviews, events, or transactions that
 resulted in a new dispatch; NO otherwise.
 */
- (BOOL)dispatch;

@end


#pragma mark -

/*!
 @abstract  Google Analytics tracker delegate.
 This delegate gets notified when
 the tracker dispatches a hit successfully, or when there was an error
 dispatching the hit. All delegate methods are optional.
 */
@protocol BXTrackerDelegate <NSObject>

@optional

/*!
 @abstract This method is invoked when a hit has been successfully submitted to
 Google Analytics.
 
 @param hitString The string representation of the hit, as sent to Google
 Analytics.
 */
- (void)hitDispatched:(NSString *)hitString;

/*!
 @abstract This method is invoked when a dispatch to Google Analytics is
 completed.
 
 @discussion Note: failed hits will be retried on the next dispatch.
 
 @param tracker The tracker object for which the dispatch was made.
 
 @param hitsDispatched The number of hits successfully submitted to Google
 Analytics.
 
 @param hitsFailedDispatch The number of hits that could not be submitted.
 */
- (void)trackerDispatchDidComplete:(BXTracker *)tracker
                  eventsDispatched:(NSUInteger)hitsDispatched
              eventsFailedDispatch:(NSUInteger)hitsFailedDispatch;

@end
