package com.example.locationsample;

import android.location.Location;
import android.os.Looper;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

import java.text.SimpleDateFormat;
import java.util.Date;

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {

    private FusedLocationProviderClient fusedLocationProviderClient; //FusedLocationProviderClientオブジェクト

    private LocationCallback locationCallback; //locationが更新されたときの動作を設定する
    private LocationRequest locationRequest; //locationの更新に関する設定をする（更新間隔や精度など。）

    private Location location; //現在の位置情報（Location）を保持する

    private GoogleMap map; //GoogleMap。OnMapReadyCallbackインタフェース内で紐付けを行ってから利用。

    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 E曜日 HH:mm:ss"); //更新日時のフォーマット。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /* fusedLocationProviderClientの準備。 */
        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this); //ここのthisは、activityのこと

        createLocationCallback(); //locationCallbackの設定。長くなるので詳しくは下で実装しているcreateLocationCallback()メソッド参照。
        createLocationRequest(); //locationRequestの設定。長くなるので詳しくは下で実装しているcreateLocationRequest()メソッド参照。

    }

    @Override
    protected void onResume() {
        super.onResume();
        startLocationUpdates(); //アクティビティがアクティブになったら測位開始。

        /* Fragment関連の準備 */
        FragmentManager fragmentManager = getSupportFragmentManager();
        SupportMapFragment mapFragment = (SupportMapFragment)fragmentManager.findFragmentById(R.id.map);

        /* mapの準備 */
        mapFragment.getMapAsync(this); //ここのthisはOnMapReadyCallbackインタフェースのこと。今回はMainActivityに実装しているためthisでOK。

    }

    @Override
    protected void onPause() {
        super.onPause();
        stopLocationUpdates(); //バッテリーの消費が激しいので、アクティビティが非アクティブになるときは止める。
    }

    /* locationCallbackの設定。 */
    private void createLocationCallback() {
        locationCallback= new LocationCallback(){
            //onLocationResultメソッドをオーバーライド。
            //このメソッドはデバイスの位置情報が利用可能になったときに呼び出される。
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);

                location = locationResult.getLastLocation(); //利用可能な最新のロケーションを取得。

                /* locationの日時、緯度、経度の取得と更新 */
                TextView dateTime = (TextView)findViewById(R.id.dateTime);
                TextView lat = (TextView)findViewById(R.id.latitude);
                TextView lng = (TextView)findViewById(R.id.longitude);

                Date updateTime = new Date(location.getTime()); //locationの日時を取得
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); //locationの緯度経度を取得

                /* ViewとFragmentの更新 */
                dateTime.setText("更新：" + dateFormat.format(updateTime));
                lat.setText("緯度：" + latLng.latitude);
                lng.setText("経度：" + latLng.longitude);

                map.addMarker(new MarkerOptions().position(latLng)); //map上にマーカーを設置。
                map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 18)); //mapのフォーカスを現在位置に変更。
                Toast.makeText(MainActivity.this, "更新されました。", Toast.LENGTH_SHORT).show(); //Toastで更新されたことを確認。
            }
        };
    }
    //locationRequestの設定。
    private void createLocationRequest() {
        locationRequest = LocationRequest.create(); //locationRequestオブジェクトの取得。
        /* 精度の設定 */
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); //高精度。GPSが優先使用される。電池をかなり消費する。
        //locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); //低精度。精度は100m程度。Wifi,モバイルネットワークの位置情報が主に使われる。
        //locationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER); //超低精度。精度は10km程度。
        //locationRequest.setPriority(LocationRequest.PRIORITY_NO_POWER); //能動的には更新しない。他のアプリで測定されたロケーション情報を流用。

        /* インターバルの設定。 */
        locationRequest.setInterval(3 * 1000); //最低何ミリ秒間隔で更新されるかを設定する。他のアプリのインターバルの影響などでインターバルの時間が長くなったり短くなったりすることがある。
        //locationRequest.setFastestInterval(3 * 1000); //インターバル（単位はミリ秒）。↑と異なり、これより短い間隔でアップデートすることはない。
    }

    //位置情報の取得開始処理。
    private void startLocationUpdates() {
        Toast.makeText(MainActivity.this, "位置情報の取得を開始します。", Toast.LENGTH_SHORT).show();
        try {
            fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper()); //←パーミッションの確認を行うか、SecurityExceptionに対処しないと、AndroidStudio上で赤い線が出る（実行は可能）。
        }catch(SecurityException e){
            e.printStackTrace();
        }
    }

    //位置情報の取得停止処理。
    private void stopLocationUpdates() {
        fusedLocationProviderClient.removeLocationUpdates(locationCallback);
    }

    //↓OnMapReadyCallbackインタフェースの抽象メソッドを実装
    @Override
    public void onMapReady(GoogleMap googleMap) {
        map = googleMap;
    }
}
