//---------------------------------------------------------------------------------------------
//
//  Compass.m
//  X-BASIC'
//
//  Created by AIG-Soft(iMac) on 2012/12/04.
//  Copyright (c) 2012-15年 AIG-Soft. All rights reserved.
//
//---------------------------------------------------------------------------------------------

#import "Compass.h"

@implementation Compass

//---------------------------------------------------------------------------------------------

-(void)startMain
// 方位情報初期化
// これをメインスレッドで実行しないと後のデリゲートが実行されない
{
	@autoreleasepool { // 別スレッドのお約束
	printSelf();
	
	locationManager=[[CLLocationManager alloc]init];
	nslog(@"locationManager=%@",locationManager);
	locationManager.delegate=self;
	
	// 真北を基準にしたヘディングを取得する位置情報サービスを開始する（らしい）
	locationManager.distanceFilter=1000;
	locationManager.desiredAccuracy=kCLLocationAccuracyKilometer;
	[locationManager startUpdatingLocation];
	
	// ヘディングの更新を開始する（らしい）
	nslog(@"方位取得開始");
	locationManager.headingFilter=1; // これ以上の角度変化があった時にイベントが発生する
	[locationManager startUpdatingHeading];
	}
}

// 取得処理開始
// datas : データ確保数
// リターン値 : YES=エラー
-(BOOL)start:(int)max_data_
{
	nslog(@"compass.start:max=%d",max_data_);
	// 指定分のデータを保存できる量
	max_datas=max_data_;
//	data=[[NSMutableArray alloc]initWithCapacity:max_datas+1]; // これではうまくいかない
	data=[[NSMutableArray alloc]init];
	// ダミーデータで配列容量を確保しておく
	// wp==rpの位置は記録できないので+1で容量を確保する必要がある
	for (int i=0;i<max_data_+1;i++) {
		[data addObject:self];
	}
	nslog(@"[data count]=%d",(int)[data count]);

	// 初期化
	[self clear];
	
	if ([CLLocationManager headingAvailable] && [CLLocationManager locationServicesEnabled]) {
		// 方位情報初期化
		// メインスレッドでないとだめらしい
		[self performSelectorOnMainThread:@selector(startMain) withObject:nil waitUntilDone:YES];
	} else {
		nslog(@"方位取得が使えない");
		return (YES);
	}
	return (NO);
}

-(void)clear
// バッファークリア
{
	rp=wp=0;
}

-(int)calcSamples
// データ個数を数える
{
	if (wp>=rp) return(wp-rp);
	// wp<rp
	return (max_datas-(rp-wp));
}

-(CLHeading *)getData
{
	printSelf();
	nslog(@"rp=%d,wp=%d,samples=%d",rp,wp,[self calcSamples]);
	if (locationManager==nil||(rp==wp)) {
		nslog(@"データなし");
		return(nil); // データはない
	}
	CLHeading *d=data[rp];
	// 読んだら消すので注意
	if (++rp>=max_datas) rp=0;
	
	return(d);
}

-(int)count
// 実記録データ数
{
	if (locationManager==nil) {
		return (0);
	}
	nslog(@"count=%d",[self calcSamples]);
	return ([self calcSamples]);
}

-(void)pause:(BOOL)fpause
// 一時停止のon/off
{
	printSelf();
	if (locationManager!=nil) {
		switch ((int)fpause) {
			case YES:
				[locationManager stopUpdatingHeading];
				break;
			case NO:
				[locationManager startUpdatingHeading];
				break;
		}
	}
}

-(void)end
{
	printSelf();
	if (locationManager!=nil) {
		[locationManager stopUpdatingHeading];
		locationManager=nil;
		 // データ読み込み用ワーク開放
	}
}

//---------------------------------------------------------------------------------------------

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
	nslog(@"方位取得エラー:%@",error);
	// データは記録しない
}

- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
// 方位情報取得(デリゲート)
{
	nslog(@"取得時間:%@",manager.location.timestamp);
	
	if (newHeading.headingAccuracy<0) {
		nslog(@"正しい値が取得できていない");
		// なので、記録しない
	} else {
		// 方角としての真北に対するする向き(度単位)
		nslog(@"角度:%f", newHeading.trueHeading);
		// 磁北に対するする向き(度単位)
		nslog(@"磁北角度:%f", newHeading.magneticHeading);
		//
		// X軸の磁束密度(マイクロテスラ単位)
		nslog(@"X軸の磁束密度:%f", newHeading.x);
		// Y軸の磁束密度(マイクロテスラ単位)
		nslog(@"Y軸の磁束密度:%f", newHeading.y);
		// Z軸の磁束密度(マイクロテスラ単位)
		nslog(@"Z軸の磁束密度:%f", newHeading.z);
		//
		[self addData:newHeading];
	}
}

-(void)addData:(CLHeading *)d
{
	printSelf();
	if (locationManager!=nil) {
		data[wp] = d;
		wp++;
		if (wp>=max_datas) wp=0;
		if (wp==rp) {
			rp++;
			if (rp>=max_datas) rp=0;
		}
		nslog(@"rp=%d,wp=%d,samples=%d",rp,wp,[self calcSamples]);
	}
}

//---------------------------------------------------------------------------------------------

-(void)dealloc
{
	printSelf();
	[self end];
}
	
@end
