package com.example.nemophila;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.example.nemophila.databinding.ActivityMainBinding;
import com.example.nemophila.entities.Post;
import com.example.nemophila.entities.Shop;
import com.example.nemophila.viewmodels.FriendViewModel;
import com.example.nemophila.viewmodels.PostsViewModel;
import com.example.nemophila.viewmodels.ShopsViewModel;
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.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.GroundOverlay;
import com.google.android.gms.maps.model.GroundOverlayOptions;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.common.collect.Maps;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
public class MapsFragment extends Fragment implements LocationListener {
ShopsViewModel shopsViewModel;
FriendViewModel friendViewModel;
PostsViewModel postsViewModel;
Nemophila nemophila;
private GoogleMap mMap;
private ActivityMainBinding binding;
private LatLng currentLatlng = null;
private LatLng initialLatlng;
private LatLng shopLatlng;
// private LatLng testLatlng;
// private LatLng testLatlng2;
private LatLng tapLatlng;
// private CameraPosition nowCamera;
// private LatLng nowLatlng;
private Marker currentMarker;
private BitmapDescriptor bd;
private boolean isLongClick;
LocationManager locationManager;
private OnMapReadyCallback callback = new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap googleMap) {
nemophila = (Nemophila) getActivity().getApplication();
mMap = googleMap;
//ViewModelへのアクセス
shopsViewModel = new ViewModelProvider(getActivity()).get(ShopsViewModel.class);
friendViewModel = new ViewModelProvider(getActivity()).get(FriendViewModel.class);
postsViewModel = new ViewModelProvider(getActivity()).get(PostsViewModel.class);
//フレンドの更新が入った時の処理(LiveDataへの購読)
friendViewModel.getFriends(nemophila.getUid());
friendViewModel.getFriendsLiveData().observe(getActivity(), friends -> {
Toast.makeText(getActivity(),
String.format("フレンドの更新を確認しました。"),
Toast.LENGTH_SHORT)
.show();
//nemophilaにセットしておく
nemophila.setFriends(friends);
});
// 店情報の更新が入った時の処理(LiveDataへの購読)
shopsViewModel.getShopsLiveData().observe(getActivity(), shops -> {
Toast.makeText(getActivity(),
String.format("表示していない店を確認しました。ピンを立てます"),
Toast.LENGTH_SHORT)
.show();
for (Shop shop : shops) {
if ( shopsViewModel.getMarker(shop) == null) { //フレンド以外の投稿のピンも立てたい場合
//各shopに対応するMarkerがなければMarkerを立てる
shopLatlng = new LatLng(shop.getLatitude(), shop.getLongitude());
System.out.println(shopLatlng);
Marker createMaker = mMap.addMarker(new MarkerOptions().position(shopLatlng).title(""));
//マーカーに店情報を持たせる
createMaker.setTag(shop);
//フィルター掛け
if ( !nemophila.getSelectGenres().isEmpty() ) {
Toast.makeText(getActivity(),
String.format("ジャンルに該当しないので非表示にします"),
Toast.LENGTH_SHORT)
.show();
createMaker.setVisible(false);
}
if ( !nemophila.getSelectFriends().isEmpty() ) {
createMaker.setVisible(false);
}
//ShopToMarkerに紐づけ
shopsViewModel.setShopAndMarker(shop, createMaker);
} else {
//すでに立っているピンをフィルター掛け
Marker setMaker = shopsViewModel.getMarker(shop);
if ( !nemophila.getSelectGenres().isEmpty() ) {
setMaker.setVisible(false);
}
if ( !nemophila.getSelectFriends().isEmpty() ) {
setMaker.setVisible(false);
}
}
}
});
// 長押しを認識した後の処理(LiveDataへの購読)
shopsViewModel.getNearShopsLiveData().observe(getActivity(), shops -> {
Toast.makeText(getActivity(),
String.format("近辺の店を確認しました。ダイアログを表示します"),
Toast.LENGTH_SHORT)
.show();
//長押し時は周辺のピンを全て取得し、ダイアログに表示する
DialogFragment dialogFragment = new MapsDialogFragment(shops);
dialogFragment.show(getActivity().getSupportFragmentManager(),"mapsdialog");
});
//初期画面の座標(現在地をロードするまで表示)
//initialLatlng = new LatLng(39,138);
initialLatlng = new LatLng(nemophila.getCameraLatitude(), nemophila.getCameraLongitude());
//初期画面に移動
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(initialLatlng, nemophila.getZoom()));
//画面が動いたとき
mMap.setOnCameraIdleListener(() -> {
//カメラの座標とZOOM倍率を保存
//nowCamera = mMap.getCameraPosition();
nemophila.setCameraLatitude(mMap.getCameraPosition().target.latitude);
nemophila.setCameraLongitude(mMap.getCameraPosition().target.longitude);
nemophila.setZoom(mMap.getCameraPosition().zoom);
//Shopの描画範囲を指定
shopsViewModel.setViewArea(nemophila.getCameraLongitude() + 1, nemophila.getCameraLatitude() + 1, nemophila.getCameraLongitude() - 1, nemophila.getCameraLatitude() - 1);
// Collection<Shop> shops = shopsViewModel.getPreShoplist();
//
// if ( shops != null ) {
// System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
// System.out.println(shops);
//
// Toast.makeText(getActivity(),
// String.format("フィルターを適応中"),
// Toast.LENGTH_SHORT)
// .show();
//
// for (Shop shop : shops) {
// // if ( shopsViewModel.getMarker(shop) != null) {
// // //すでに立っているピンをフィルター掛け
// // Marker setMaker = shopsViewModel.getMarker(shop);
// // if (!nemophila.getSelectGenres().isEmpty()) {
// // Toast.makeText(getActivity(),
// // String.format("ジャンルに該当しないピンを全て非表示にします"),
// // Toast.LENGTH_SHORT)
// // .show();
// // setMaker.setVisible(false);
// // }
// // if (!nemophila.getSelectFriends().isEmpty()) {
// // setMaker.setVisible(false);
// // }
// // }
// // System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
// //}
// }
// }
});
// test用 座標を確認するため
// タップした時のリスナーをセット
mMap.setOnMapClickListener(tapLocation -> {
// map(ピン以外)をtapされた位置の緯度経度
tapLatlng = new LatLng(tapLocation.latitude, tapLocation.longitude);
Toast.makeText(getActivity(),
String.format("%s", tapLatlng),
Toast.LENGTH_SHORT)
.show();
});
//長押し時に店を作成し、その座標にピンを立てる
//長押し時にその座標を保存し、投稿画面に移り、Shop作成完了時にはピンを立て、Shop画面に移行
mMap.setOnMapLongClickListener(longpushLocation -> {
//長押しされた位置の緯度経度を取得
//LatLng newlocation = new LatLng(longpushLocation.latitude, longpushLocation.longitude);
//長押し座標を画面中心にしておく
//zoomMap(longpushLocation.latitude, longpushLocation.longitude);
//Nemophilaに座標を保存
nemophila.setCurrentLatitude(longpushLocation.latitude);
nemophila.setCurrentLongitude(longpushLocation.longitude);
//長押しした場合は今からShopを作成するので、CurrentShopをnullで登録しておく
nemophila.setCurrentShop(null);
//長押しでダイアログを表示
//テスト用
//shopsViewModel.longClickViewArea(longpushLocation.longitude+1, longpushLocation.latitude+1, longpushLocation.longitude-1, longpushLocation.latitude-1);
//本番環境は↓の範囲で
shopsViewModel.longClickViewArea(longpushLocation.longitude+0.001, longpushLocation.latitude+0.001, longpushLocation.longitude-0.001, longpushLocation.latitude-0.001);
});
// ピンをクリックした場合
mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker marker) {
//店の詳細と投稿一覧を表示
//ここでshopActivityを呼び出す
//下からクリックしたことを通知
//Toast.makeText(getActivity(), "ピンクリック", Toast.LENGTH_SHORT).show();
//現在地マーカーをクリックしたときのみ例外
if(marker.getTag() == null) {
//以下の処理をストップ
return false;
}
//選んだ店をsetする
nemophila.setCurrentShop((Shop) marker.getTag());
System.out.println(nemophila.getCurrentShop().getName());
//ShopActivity画面に遷移
Intent intent = new Intent(getActivity(), ShopActivity.class);
startActivity(intent);
return false;
}
});
}
};
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_maps, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//binding = ActivityMainBinding.inflate(getLayoutInflater());
//getActivity().setContentView(binding.getRoot());
if (ActivityCompat.checkSelfPermission(
getContext(),
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissionLauncher.launch(
Manifest.permission.ACCESS_FINE_LOCATION);
}
else{
locationStart();
}
// // Obtain the SupportMapFragment and get notified when the map is ready to be used.
// SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
// .findFragmentById(R.id.map);
// assert mapFragment != null;
// mapFragment.getMapAsync(this);
SupportMapFragment mapFragment =
(SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
if (mapFragment != null) {
mapFragment.getMapAsync(callback);
}
//現在地アイコン用の準備
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_current);
Bitmap afterBitmap = Bitmap.createScaledBitmap(bitmap, 100, 100, true);
bd = BitmapDescriptorFactory.fromBitmap(afterBitmap);
}
private void zoomMap(double latitude, double longitude) {
// 表示する東西南北の緯度経度を設定
double south = latitude * (1 - 0.00005);
double west = longitude * (1 - 0.00005);
double north = latitude * (1 + 0.00005);
double east = longitude * (1 + 0.00005);
LatLng latlng = new LatLng(latitude, longitude);
// LatLngBounds (LatLng southwest, LatLng northeast)
//左下、右上
LatLngBounds bounds = LatLngBounds.builder()
.include(new LatLng(south, west))
.include(new LatLng(north, east))
.build();
int width = getResources().getDisplayMetrics().widthPixels;
int height = getResources().getDisplayMetrics().heightPixels;
// static CameraUpdate.newLatLngBounds(LatLngBounds bounds, int width, int height, int padding)
mMap.moveCamera(CameraUpdateFactory.
newLatLngBounds(bounds, width, height, 0));
//ズーム処理
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latlng, nemophila.getZoom()));
}
//現在地の表示
private void setIcon(double latitude, double longitude) {
//現在地をLatLng型で取得
LatLng current_location = new LatLng(latitude, longitude);
//初回現在地取得時
if (currentMarker == null) {
currentMarker=mMap.addMarker(new MarkerOptions().position(current_location).title("現在地").icon(bd));
} else {
//2回目移行
currentMarker.setPosition(current_location);
}
}
private final ActivityResultLauncher<String>
requestPermissionLauncher = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),
isGranted -> {
if (isGranted) {
locationStart();
}
else {
Toast toast = Toast.makeText(getActivity(),
"これ以上なにもできません", Toast.LENGTH_SHORT);
toast.show();
}
});
//現在地の取得
@SuppressLint("MissingPermission")
private void locationStart(){
Log.d("debug","locationStart()");
// LocationManager インスタンス生成
locationManager =
(LocationManager) getContext().getSystemService(getContext().LOCATION_SERVICE);
if (locationManager != null && locationManager.isProviderEnabled(
LocationManager.GPS_PROVIDER)) {
Log.d("debug", "location manager Enabled");
} else {
// GPSを設定するように促す
Intent settingsIntent =
new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(settingsIntent);
Log.d("debug", "not gpsEnable, startActivity");
}
if (ContextCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION,}, 1000);
Log.d("debug", "checkSelfPermission false");
return;
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
1000, 50, this);
}
@Override
public void onLocationChanged(Location location) {
//初期画面は現在地を中心にするため...
if (currentLatlng == null){
//↓現在地ロード後画面中心を現在地にする場合
//zoomMap(location.getLatitude(), location.getLongitude());
//ロード画面の終了
//getView().findViewById(R.id.LL_Load).setVisibility(View.GONE);
//現在地ボタンを表示
getView().findViewById(R.id.currentButton).setVisibility(View.VISIBLE);
ImageButton button1 = getView().findViewById(R.id.currentButton);
button1.setOnClickListener( v -> {
Log.d("debug", "currentbutton, 現在地にカメラを移動");
System.out.println(shopsViewModel.getShopsLiveData().getValue());
//現在地にカメラを移動
zoomMap(currentLatlng.latitude, currentLatlng.longitude);
});
}
//現在地が変更されるたびに現在地アイコンを移動
//LatLng型で受け取っておく
currentLatlng = new LatLng(location.getLatitude(), location.getLongitude());
//現在地アイコンを表示.このsetIcon内にzoomMap処理もあるので注意
setIcon(location.getLatitude(),location.getLongitude());
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
}