package com.markjmind.uni.boot;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Build;
import android.os.PowerManager;
import android.view.View;
import com.markjmind.uni.R;
import com.markjmind.uni.UniFragment;
import com.markjmind.uni.common.Store;
import com.markjmind.uni.util.ReflectionUtil;
import java.util.ArrayList;
import java.util.Stack;
/**
* <br>捲土重來<br>
*
* @author 오재웅(JaeWoong-Oh)
* @email markjmind@gmail.com
* @since 2016-06-02
*/
public class FragmentBuilder {
private static final String DEFALUT_TAG = "UNI";
private Activity activity;
private FragmentManager fragmentManager;
private FragmentTransaction transaction;
private boolean allowingStateLoss = false;
private boolean history = true;
private Store param;
private UniFragment.OnFinishedListener finishedListener;
protected FragmentBuilder(Activity activity){
this.activity = activity;
}
public static <T extends UniBoot>T setContentView(Activity activity, Class<T> boot){
return (T) ReflectionUtil.getInstance(boot).initLayout(activity);
}
/**
* Class<T>로 지정한 Type의 UniBoot 객체를 리턴한다.<br>
* UniBoot를 사용하지 않았다면 null을 리턴한다.
* @param boot UniBoot Type
* @param <T> UniBoot를 상속 받은 Class
* @return T Type의 UniBoot 객체
*/
public static <T extends UniBoot>T getBoot(Activity activity, Class<T> boot){
View rootView = activity.findViewById(R.id.uni_boot_frame_root);
T bootStrap = null;
if(rootView!=null){
bootStrap = (T)rootView.getTag();
if(bootStrap==null){
bootStrap = ReflectionUtil.getInstance(boot);
if(bootStrap!=null){
bootStrap.initLayout(activity);
}
}
}
return bootStrap;
}
public static FragmentBuilder getBuilder(Activity activity){
return new FragmentBuilder(activity);
}
public static FragmentBuilder getBuilder(UniFragment uniFragment){
return new FragmentBuilder(uniFragment.getActivity());
}
public void replace(int parentsID, UniFragment uniFragment, String tag){
uniFragment.setRefreshBackStack(true);
String stackName = FragmentBuilder.getDefalutStack(parentsID);
setOption(parentsID, uniFragment);
FragmentTransaction transaction = getTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(parentsID, uniFragment, tag);
if(history){
if ( allowingStateLoss ) {
transaction.addToBackStack(stackName)
.commitAllowingStateLoss();
}
else {
transaction.addToBackStack(stackName).commit();
}
}else{
if ( allowingStateLoss || !isScreenOn() ) {
transaction.commitAllowingStateLoss();
}
else {
try {
transaction.commit();
} catch ( IllegalStateException e ) {
e.printStackTrace();
}
}
}
}
private void setOption(int parentsID, UniFragment uniFragment){
if(param!=null){
uniFragment.param.putAll(param);
}
uniFragment.setParentsViewID(parentsID);
if(finishedListener != null){
uniFragment.setOnFinishedListener(finishedListener);
}
}
public UniFragment getCurrentFragment(int parentsID){
return getCurrentFragment(FragmentBuilder.getDefalutStack(parentsID));
}
private UniFragment getCurrentFragment(String tagName){
return (UniFragment)(getFragmentManager().findFragmentByTag(tagName));
}
public void replace(int parentsID, UniFragment uniFragment){
// this.replace(parentsID, uniFragment, ""+uniFragment.getClass());
this.replace(parentsID, uniFragment, FragmentBuilder.getDefalutStack(parentsID));
}
private boolean isScreenOn() {
PowerManager powerManager = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
boolean result = false;
if ( Build.VERSION.SDK_INT >= 20 ) result = powerManager.isInteractive();
else if ( Build.VERSION.SDK_INT < 20 ) result = powerManager.isScreenOn();
return result;
}
public FragmentBuilder popBackStackClear(boolean clearAll, int parentsID){
String stackName = FragmentBuilder.getDefalutStack(parentsID);
if(containStackEntry(stackName)) {
try {
int entry = getFragmentManager().getBackStackEntryCount();
Stack<UniFragment> uniFragments = new Stack<>();
for (int i = entry - 1; i >= 0; i--) {
String tagName = getFragmentManager().getBackStackEntryAt(i).getName();
if (tagName.contains(stackName)) {
getFragmentManager().popBackStackImmediate();
} else {
UniFragment uniFragment = getCurrentFragment(tagName);
uniFragments.push(uniFragment);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.remove(uniFragment);
getFragmentManager().executePendingTransactions();
transaction.commitAllowingStateLoss();
getFragmentManager().popBackStackImmediate();
}
}
if (clearAll) {
getFragmentManager().beginTransaction()
.remove(getCurrentFragment(stackName))
.commitAllowingStateLoss();
}
int stackCount = uniFragments.size();
if (stackCount > 0) {
for (int i = 0; i < stackCount; i++) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
UniFragment uniFragment = uniFragments.pop();
uniFragment.setRefreshBackStack(false);
String tagName = getDefalutStack(uniFragment.getParentsViewID());
transaction.addToBackStack(tagName);
transaction.replace(uniFragment.getParentsViewID(), uniFragment, tagName);
transaction.commitAllowingStateLoss();
}
}
}catch (IllegalStateException e){
// e.printStackTrace();
if(stackName!=null) {
UniFragment currentFragment = getCurrentFragment(stackName);
if (currentFragment != null) {
currentFragment.getFragmentStack().clearHistoryOnResume(clearAll, parentsID);
}
}
}
}
return this;
}
public FragmentBuilder popBackStackClear(boolean clearAll) {
if(clearAll) {
int entry = getFragmentManager().getBackStackEntryCount();
ArrayList<String> stackNames = new ArrayList<>();
for (int i = entry - 1; i >= 0; i--) {
String tagName = getFragmentManager().getBackStackEntryAt(i).getName();
if (!stackNames.contains(tagName)) {
stackNames.add(tagName);
}
}
try {
getFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
for (String tagName : stackNames) {
getFragmentManager().beginTransaction()
.remove(getCurrentFragment(tagName))
.commitAllowingStateLoss();
}
}catch (IllegalStateException e){
// e.printStackTrace();
String stackName = getFirstStackName();
if(stackName!=null) {
UniFragment currentFragment = getCurrentFragment(stackName);
if (currentFragment != null) {
currentFragment.getFragmentStack().clearHistoryOnResume(true, null);
}
}
}
}else{
popBackStackClear();
}
return this;
}
private FragmentBuilder popBackStackClear() {
try {
getFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}catch (IllegalStateException e){
// e.printStackTrace();
String stackName = getFirstStackName();
if(stackName!=null) {
UniFragment currentFragment = getCurrentFragment(stackName);
if (currentFragment != null) {
currentFragment.getFragmentStack().clearHistoryOnResume(false, null);
}
}
}
return this;
}
public boolean popBackStack(int parentsID) {
boolean result = false;
String stackName = FragmentBuilder.getDefalutStack(parentsID);
if(containStackEntry(stackName)) {
try {
int entry = getFragmentManager().getBackStackEntryCount();
Stack<UniFragment> uniFragments = new Stack<>();
for (int i = entry - 1; i >= 0; i--) {
String tagName = getFragmentManager().getBackStackEntryAt(i).getName();
if (tagName.contains(stackName)) {
getFragmentManager().popBackStackImmediate();
result = true;
break;
} else {
UniFragment uniFragment = getCurrentFragment(tagName);
uniFragments.push(uniFragment);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.remove(uniFragment);
getFragmentManager().executePendingTransactions();
transaction.commitAllowingStateLoss();
getFragmentManager().popBackStackImmediate();
}
}
int stackCount = uniFragments.size();
if (stackCount > 0) {
for (int i = 0; i < stackCount; i++) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
UniFragment uniFragment = uniFragments.pop();
uniFragment.setRefreshBackStack(false);
String tagName = getDefalutStack(uniFragment.getParentsViewID());
transaction.addToBackStack(tagName);
transaction.replace(uniFragment.getParentsViewID(), uniFragment, tagName);
transaction.commitAllowingStateLoss();
}
}
}catch (IllegalStateException e){
if(stackName!=null) {
UniFragment currentFragment = getCurrentFragment(stackName);
if (currentFragment != null) {
currentFragment.getFragmentStack().popStackOnResume(parentsID);
}
}
}
}
return result;
}
public void popBackStack() {
if(getFragmentManager().getBackStackEntryCount()>0) {
try {
getFragmentManager().popBackStackImmediate();
}catch (IllegalStateException e){
String stackName = getFirstStackName();
if(stackName!=null) {
UniFragment currentFragment = getCurrentFragment(stackName);
if (currentFragment != null) {
currentFragment.getFragmentStack().popStackOnResume(null);
}
}
}
}
}
private int getStackEntryCount(String stackName){
int entry = getFragmentManager().getBackStackEntryCount();
int count = 0;
for (int i = entry - 1; i >= 0; i--) {
if (getFragmentManager().getBackStackEntryAt(i).getName().contains(stackName)) {
count++;
}
}
return count;
}
private boolean equalsStackEntry(String stackName){
int entry = getFragmentManager().getBackStackEntryCount();
for (int i = entry - 1; i >= 0; i--) {
if (getFragmentManager().getBackStackEntryAt(i).getName().equals(stackName)) {
return true;
}
}
return false;
}
private boolean containStackEntry(String stackName){
int entry = getFragmentManager().getBackStackEntryCount();
for (int i = entry - 1; i >= 0; i--) {
if (getFragmentManager().getBackStackEntryAt(i).getName().contains(stackName)) {
return true;
}
}
return false;
}
private String getFirstStackName(){
int entry = getFragmentManager().getBackStackEntryCount();
if(entry>0){
return getFragmentManager().getBackStackEntryAt(entry-1).getName();
}
return null;
}
public FragmentBuilder setHistory(boolean isHistory){
history = isHistory;
return this;
}
public FragmentBuilder addParam(String key, Object value){
if(param==null){
param = new Store();
}
param.add(key, value);
return this;
}
public FragmentTransaction getTransaction(){
if(transaction == null){
this.transaction = getFragmentManager().beginTransaction();
}
return transaction;
}
public FragmentBuilder setOnFinishedListener(UniFragment.OnFinishedListener finishedListener){
this.finishedListener = finishedListener;
return this;
}
/**
* Sync 지정옵션
* @param isSync
* @return
*/
// public FragmentBuilder setSync(boolean isSync){
// fragment.setAsync(isSync);
// return this;
// }
/**
* @param isAllowingStateLoss
* @return
*/
public FragmentBuilder setAllowingStateLoss(boolean isAllowingStateLoss) {
this.allowingStateLoss = isAllowingStateLoss;
return this;
}
public FragmentManager getFragmentManager(){
if(fragmentManager == null){
fragmentManager = activity.getFragmentManager();
}
return fragmentManager;
}
public static String getDefalutStack(int parentsID){
return DEFALUT_TAG+parentsID;
}
}