public class AboutFragment extends Fragment {
    public static final String TAG = AboutFragment.class.getSimpleName();
    private static final boolean DEBUG = Config.DEBUG;
    private ScrollView _sv_about;
    private TextView _tv_survey;

    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){

        View view = inflater.inflate(R.layout.about, container, false);
        TextView aboutText = view.findViewById(R.id.AboutTextL1);

        aboutText.setText(
                String.format(getString(R.string.about_licence_l1),
                        DeviceUtil.getVersionName(Objects.requireNonNull(getActivity())),
                        DeviceUtil.getVersionCode(getActivity())+""
                )
        );

        _sv_about = view.findViewById(R.id.sv_about);
        Animation translatebu= AnimationUtils.loadAnimation(getActivity(), R.anim.about);
        _sv_about.startAnimation(translatebu);

        return view;
    }

    private View.OnClickListener onSurverClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            UITools.viewLink(Objects.requireNonNull(getActivity()), _tv_survey.getText().toString());
        }
    };
} public class AliasFragment extends Fragment {

    public static final String TAG = AliasFragment.class.getSimpleName();
    private Button mAcceptButton;
    private EditText mAliasEdit;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_alias,container,false);
        mAcceptButton = view.findViewById(R.id.bt_alias_accept);
        mAliasEdit = view.findViewById(R.id.et_alias_alias);
        mAliasEdit.setOnKeyListener(getMain());
        mAcceptButton.setOnClickListener(onAliasAcceptListener);

        return view;

    }

    private View.OnClickListener onAliasAcceptListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            String alias =mAliasEdit.getText().toString();
            if(alias.length()!=0) {
                Storage.setCurrentAlias(getActivity(),alias);
                getMain().removeAliasFragment();
                DeviceUtil.hideKeyBoard(getActivity());
            }
            else UITools.showToast(getActivity(),R.string.msg_alias_help);
        }
    };

    private MainActivity getMain() {
        return ((MainActivity)getActivity());
    }


} public class ConfirmDialogFragment extends DialogFragment {

    public static final String TAG = ConfirmDialogFragment.class.getSimpleName();
    private AppCompatButton mButtonSMS;
    private AppCompatButton mButtonShare;
    private boolean sms_enable;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        int theme=R.style.BaseTheme_Dialog;
        int style = DialogFragment.STYLE_NORMAL;
        setStyle(style, theme);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_dialog_confirm, container, false);

        mButtonSMS = v.findViewById(R.id.bt_alert_dialog_sms);
        mButtonShare = v.findViewById(R.id.bt_alert_dialog_share);

        mButtonSMS.setOnClickListener(onSMSClickListener);
        mButtonShare.setOnClickListener(onShareClickListener);

        validateSMS();

        return v;
    }

    private void validateSMS() {

        if (Storage.getRingsEnable(getActivity()).size() == 0 || Storage.getRings(getActivity()).size() == 0) {
            ColorStateList csl = new ColorStateList(new int[][]{new int[0]}, new int[]{0xffffcc00});
            mButtonSMS.setSupportBackgroundTintList(csl);
            sms_enable = false;
        }
        else {
            ColorStateList csl = new ColorStateList(new int[][]{new int[0]}, new int[]{0xffffcc00});
            mButtonSMS.setSupportBackgroundTintList(csl);
            sms_enable = true;
        }

    }

    private View.OnClickListener onSMSClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Logger.d(TAG, "onSMSClickListener");
            if (!sms_enable) {
                Logger.i(TAG,""+getString(R.string.msg_alert_not_rings));
                getMain().showSnackLong(getString(R.string.msg_alert_not_rings));
            }
            else {
                getMain().sendSMS();
                Objects.requireNonNull(getDialog()).dismiss();
            }
        }
    };


    private View.OnClickListener onShareClickListener = view -> {
        Logger.d(TAG, "onShareClickListener");
        getMain().shareLocation();
        Objects.requireNonNull(getDialog()).dismiss();
    };

    @Override
    public void onResume() {
        super.onResume();
        validateSMS();
    }

    private MainActivity getMain() {
        return ((MainActivity) getActivity());
    }

} public class ContactsRingFragment extends DialogFragment {

    public static final String TAG = ContactsRingFragment.class.getSimpleName();
    private static final boolean DEBUG = Config.DEBUG;

    private Button mButtonPicker;
    private Button mButtonSave;

    private ListContactsAdapter mContactsAdapter;
    private RecyclerView mContactsRecycler;
    private TextView mEmptyMessage;
    private EditText mEditRingName;
    private String name;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        int theme = android.R.style.Theme_DeviceDefault_Light_Dialog_Alert;
        int theme = R.style.BaseTheme_DialogHeigh;
        int style = DialogFragment.STYLE_NORMAL;
        setStyle(style,theme);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_ring_edit, container, false);

        mEditRingName = view.findViewById(R.id.et_ring_edit_name);
        mEmptyMessage = view.findViewById(R.id.tv_ring_contacts_empty);
        mButtonPicker = view.findViewById(R.id.bt_ring_edit_pick_contact);
        mButtonSave   = view.findViewById(R.id.bt_ring_edit_save);
        mContactsRecycler= view.findViewById(R.id.rv_contacts);
        mButtonPicker.setOnClickListener(onPickerContactListener);
        mButtonSave.setOnClickListener(onSaveButtonListener);

        GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 1);
        mContactsRecycler.setLayoutManager(gridLayoutManager);

        mContactsAdapter= new ListContactsAdapter();
        mContactsAdapter.setOnItemClickListener(onItemClickListener);
        mContactsRecycler.setAdapter(mContactsAdapter);

        ItemTouchHelper.Callback callback = new ItemTouchHelperCallback(mContactsAdapter);
        ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
        touchHelper.attachToRecyclerView(mContactsRecycler);

        return view;

    }

    public void addConctact(Contact contact){
        if(DEBUG)Log.d(TAG,"addConctact: "+contact.toString());
        mEmptyMessage.setVisibility(View.GONE);
        mContactsRecycler.setVisibility(View.VISIBLE);
        mContactsAdapter.addItem(0,contact);
    }

    public List<Contact> getContacts() {
        return mContactsAdapter.getContacts();
    }

    public class ItemTouchHelperCallback extends ItemTouchHelper.Callback {

        private final ItemTouchHelperAdapter mAdapter;

        public ItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
            mAdapter = adapter;
        }

        @Override
        public boolean isLongPressDragEnabled() {
            return true;
        }

        @Override
        public boolean isItemViewSwipeEnabled() {
            return true;
        }

        @Override
        public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

            int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
            int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
            return makeMovementFlags(dragFlags, swipeFlags);

        }

        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
            if (DEBUG) Log.d(TAG, "ItemTouchHelperCallback: onMove");
            return true;
        }

        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
            mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
        }

    }

    @Override
    public void onDestroy() {
        if(DEBUG)Log.d(TAG,"onDestroy");
        super.onDestroy();
    }


    private boolean isValidData() {

        name = mEditRingName.getText().toString();
        if(name.length()==0){
            UITools.showToast(getActivity(),R.string.error_ring_empty_name);
            return false;
        }
        else if (mContactsAdapter.getItemCount()==0){
            UITools.showToast(getActivity(),R.string.error_ring_empty_contacts);
            return false;
        }
        return true;
    }

    private Ring saveData() {
        Ring ring = new Ring();
        ring.setName(name);
        ring.setContacts(mContactsAdapter.getContacts());
        ring.setDescription(""+mContactsAdapter.getItemCount()+" "+getString(R.string.ring_desc_contacts));
        return ring;
    }

    private OnItemClickListener onItemClickListener = new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
            Logger.d(TAG, "OnItemClickListener => Clicked: " + position + ", index " + mContactsRecycler.indexOfChild(view));
        }
    };

    private View.OnClickListener onPickerContactListener = view -> getMain().getContact();

    private View.OnClickListener onSaveButtonListener = view -> {
        if(isValidData()){
            Logger.d(TAG,"saving ring..");
            getMain().getRingsFragment().addRing(saveData());
            getDialog().dismiss();
        }
    };

    private MainActivity getMain() {
        return ((MainActivity)getActivity());
    }


} public class InputDialogFragment extends DialogFragment {

    public static final String TAG = InputDialogFragment.class.getSimpleName();
    private static final String TRACK_ID = "trackId";
    private static final boolean DEBUG = Config.DEBUG;

    private EditText mEditAlias;
    private Button mButtonContinue;
    private String trackId;
    private String alias;

    public static InputDialogFragment newInstance(String trackId){

        InputDialogFragment dialog = new InputDialogFragment();

        // Supply num input as an argument.
        Bundle args = new Bundle();
        args.putString(TRACK_ID, trackId);
        dialog.setArguments(args);

        if(DEBUG) Log.d(TAG, "InputDialogFragment for trackId" + trackId);

        return dialog;

    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        trackId=getArguments().getString(TRACK_ID);

        int style = DialogFragment.STYLE_NO_TITLE;
        setStyle(style, android.R.style.Theme_DeviceDefault_Light_Dialog_Alert);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_dialog_input, container, false);

        mEditAlias = (EditText)v.findViewById(R.id.et_alias_name);
        mButtonContinue = (Button)v.findViewById(R.id.bt_alias_continue);
        mButtonContinue.setOnClickListener(onClickContinueListener);

        return v;

    }

    private View.OnClickListener onClickContinueListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
//            if(isValidData())getMain().newTrackId(trackId,alias);
            getDialog().dismiss();
        }
    };

    private boolean isValidData() {
        alias = mEditAlias.getText().toString();
        if(alias.length()==0){
            UITools.showToast(getActivity(),R.string.msg_track_alias);
            return false;
        }
        return true;
    }


    private MainActivity getMain() {
        return ((MainActivity) getActivity());
    }


} public class MainFragment extends Fragment {

    public static final String TAG = MainFragment.class.getSimpleName();
    private Button mMainButton;
    private SwitchCompat mServiceButton;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_main,container,false);
        mMainButton = view.findViewById(R.id.bt_home_main_alert);
        mServiceButton = view.findViewById(R.id.tb_home_enable_tracking);
        mMainButton.setOnClickListener(onMainButtonListener);
        mServiceButton.setOnCheckedChangeListener(onServiceEnableChecked);

        return view;

    }

    public void setServiceButtonEnable(boolean enable){
        mServiceButton.setChecked(enable);
    }

    private View.OnClickListener onMainButtonListener = view -> getMain().showConfirmAlertFragment();

    private CompoundButton.OnCheckedChangeListener onServiceEnableChecked = (compoundButton, isChecked) -> {
        if(isChecked)getMain().startTrackLocationService();
        else getMain().stopTrackLocationService();
    };

    private MainActivity getMain() {
        return ((MainActivity)getActivity());
    }


} public class MapPartnersFragment extends Fragment {

    public static final String TAG = MapPartnersFragment.class.getSimpleName();
    private static final boolean DEBUG = Config.DEBUG;

    private RecyclerView mPartnersRecycler;
    private ListPartnersAdapter mPartnersAdapter;
    private TextView mEmptyMessage;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_partners,container,false);

        mEmptyMessage = (TextView)view.findViewById(R.id.tv_partners_empty_list);
        mPartnersRecycler = (RecyclerView) view.findViewById(R.id.rv_partners);



        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
        GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 1);
        mPartnersRecycler.setLayoutManager(layoutManager);

        mPartnersAdapter = new ListPartnersAdapter();
        mPartnersAdapter.setOnItemClickListener(onItemClickListener);
//        mPartnersAdapter.addItem(0,new Partner("testing","Tuesday 12, 20:35"));
//        mPartnersAdapter.addItem(0,new Partner("testing","Tuesday 13, 20:35"));
//        mPartnersAdapter.addItem(0,new Partner("testing","Tuesday 14, 20:35"));
//        mPartnersAdapter.addItem(0,new Partner("testing","Tuesday 15, 20:35"));
        mPartnersRecycler.setAdapter(mPartnersAdapter);

        ItemTouchHelper.Callback callback = new ItemTouchHelperCallback(mPartnersAdapter);
        ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
        touchHelper.attachToRecyclerView(mPartnersRecycler);

        refreshUI();

        return view;
    }

    public void addPartner(Partner partner) {

        if(DEBUG)Log.d(TAG, "addPartner: " + partner.toString());
        mPartnersAdapter.addItem(0, partner);
//        Storage.saveRing(getActivity(),partner);
        refreshUI();

    }

    private void refreshUI(){
        if(mPartnersAdapter.getItemCount()>0){
            mEmptyMessage.setVisibility(View.GONE);
            mPartnersRecycler.setVisibility(View.VISIBLE);
        }else{
            mPartnersRecycler.setVisibility(View.GONE);
            mEmptyMessage.setVisibility(View.VISIBLE);
        }

    }

    public class ItemTouchHelperCallback extends ItemTouchHelper.Callback {

        private final ItemTouchHelperAdapter mAdapter;

        public ItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
            mAdapter = adapter;
        }

        @Override
        public boolean isLongPressDragEnabled() {
            return true;
        }

        @Override
        public boolean isItemViewSwipeEnabled() {
            return true;
        }

        @Override
        public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

            int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
            int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
            return makeMovementFlags(dragFlags, swipeFlags);

        }

        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
            if (DEBUG) Log.d(TAG, "ItemTouchHelperCallback: onMove");
            return true;
        }

        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
            if (DEBUG) Log.d(TAG, "ItemTouchHelperCallback: onSwiped: direction="+direction);
//            int position = viewHolder.getAdapterPosition();
//            if(direction==16) {
//                Storage.removeRing(getActivity(), mPartnersAdapter.getItem(position));
//                mAdapter.onItemDismiss(position);
//            }else if(direction==32){
//                Ring ring = mPartnersAdapter.getItem(position);
//                boolean enable = !ring.isEnable();
//                Storage.enableRing(getActivity(), ring, enable);
//                mAdapter.onItemDisable(position,enable);
//            }
//            refreshUI();
        }

    }

    private MainActivity getMain() {
        return ((MainActivity)getActivity());
    }

    private AdapterView.OnItemClickListener onItemClickListener = new AdapterView.OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
            if(DEBUG) Log.d(TAG, "OnItemClickListener => Clicked: " + position + ", index " + mPartnersRecycler.indexOfChild(view));
        }
    };

    private View.OnClickListener onRingAddClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(DEBUG) Log.d(TAG, "onRingAddClickListener");
            getMain().showAddContactsRingFragment();
        }
    };

    @Override
    public void onDestroy() {
        super.onDestroy();
    }


} public class MapTasksFragment extends SupportMapFragment implements OnMapClickListener, OnMarkerClickListener, OnMapLongClickListener {

    public static final String TAG = MapTasksFragment.class.getSimpleName();
    private static final boolean DEBUG = Config.DEBUG && Config.DEBUG_MAP;

    private static final int ANIM_TIME = 1600;
    private GoogleMap map;

    private HashMap<Track, Marker> hmMarks = new HashMap<Track, Marker>();
    private HashMap<Long, String> hmIDs = new HashMap<Long, String>();

    //    private MGPlatformApi platformApi = new MGPlatformApi();
    private Polyline lastPoline;

    public void initMap(GoogleMap map) {

        this.map = map;

        if (DEBUG) Log.d(TAG, "initMap..");
        UiSettings settings = map.getUiSettings();

        settings.setAllGesturesEnabled(true);
        settings.setZoomControlsEnabled(false);
        settings.setMyLocationButtonEnabled(true);
        map.setMyLocationEnabled(true);
        map.setOnMarkerClickListener(this);

        map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
        map.setOnMapClickListener(this);

        //Setting on long click listener
        map.setOnMapLongClickListener(this);

//        animToPosition(new LatLng(4.65149, -74.05929)); // Default Bogot?

    }


    public void addPoints(List<Track> data) {
        Iterator<Track> it = data.iterator();
        while (it.hasNext()) {
            Track track = it.next();
            if (!hmIDs.containsKey(track.upd)) addMark(track);
            else if (DEBUG) Log.d(TAG, "skip add mark");
        }
    }

    public void addMark(Track track) {
        if (DEBUG)Log.d(TAG,"addMark: "+track.toString());
        Marker marker = map.addMarker(new MarkerOptions()
                        .position(new LatLng(track.lat, track.lon))
                        .title(track.alias)
        );
        hmIDs.put(track.upd, marker.getId());
        hmMarks.put(track, marker);
        animToPosition(new LatLng(track.lat,track.lon));
        if (DEBUG) Log.d(TAG, "[MAP_FRAGMENT] addMark: " + marker.getId());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View mapView = super.onCreateView(inflater, container, savedInstanceState);

//        moveMyLocationButton(mapView);

        return mapView;

    }

    /*
    private void moveMyLocationButton(View mapView) {

        // Get the button vie
        View locationButton = ((View) mapView.findViewById(1).getParent()).findViewById(2);

        // and next place it, for exemple, on bottom right (as Google Maps app)
        RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams) locationButton.getLayoutParams();
        // position on right bottom
        rlp.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
        rlp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
        rlp.setMargins(0, 0, 40, 40);

    }*/

    public void animToPosition(LatLng pos) {
        if (pos != null) {
            if (DEBUG)
                Log.d(TAG, "[MAP_FRAGMENT] animateMark at: " + pos.latitude + "," + pos.longitude);
            CameraUpdate center = CameraUpdateFactory.newLatLngZoom(pos, Config.map_zoom_init);
            map.animateCamera(center, ANIM_TIME, null);
        } else if (DEBUG) Log.d(TAG, "[MAP_FRAGMENT] animateMark SKIP! pos is NULL");

    }

    @Override
    public void onMapClick(LatLng latLng) {
        if (DEBUG)
            Log.d(TAG, "[MAP_FRAGMENT] onMapClick: " + latLng.latitude + "," + latLng.longitude);

    }

    @Override
    public boolean onMarkerClick(Marker marker) {
        if (DEBUG) Log.d(TAG, "[MAP_FRAGMENT] onMarkerClick: " + marker.getId());
        return false;
    }

    @Override
    public void onMapLongClick(LatLng latLng) {
        if (DEBUG)
            Log.d(TAG, "[MAP_FRAGMENT] onMapLongClick: " + latLng.latitude + "," + latLng.longitude);

    }
//
//    public void paintRoute(RouteResponse routeResponse) {
//
//        GeometryList routeLines = routeResponse.geometry;
//        if (routeLines != null) {
//            PolylineOptions rectOptions = new PolylineOptions();
//            for (ArrayList<Double> pairLatLon : routeLines.coordinates) {
//                rectOptions.add(new LatLng(pairLatLon.get(1), pairLatLon.get(0)));
//            }
//
//            if (lastPoline != null) lastPoline.remove();
//            lastPoline = map.addPolyline(rectOptions);
//            fixZoom(lastPoline);
//
//        } else {
//
//            if (DEBUG) Log.d(TAG, "[MAP_FRAGMENT] paintRoute !FAIL!");
//            UITools.showToast(getActivity(), R.string.toast_route_traced_error);
//
//        }
//
//    }


    private void fixZoom(Polyline route) {

        List<LatLng> points = route.getPoints();
        LatLngBounds.Builder bc = new LatLngBounds.Builder();

        for (LatLng item : points) {
            bc.include(item);
        }
        map.moveCamera(CameraUpdateFactory.newLatLngBounds(bc.build(), 50));

    }

    public void addPoints(Map<String, Object> tracks, String trackId) {
        if (tracks != null) {
            List<Track> data = new ArrayList<>();
            if (DEBUG) Log.d(TAG, "data: " + tracks.toString());
            Iterator<Object> it = tracks.values().iterator();
            while (it.hasNext()) {
                Map<String, Object> fbtrack = (Map<String, Object>) it.next();
                Track track = getTrack(trackId, fbtrack);
                data.add(track);
            }
            addPoints(data);
        } else if (DEBUG) Log.w(TAG, "no data");
    }

    @NonNull
    private static Track getTrack(String trackId, Map<String, Object> fbtrack) {
        Track track = new Track();
        track.trackId = trackId;
        track.alias=fbtrack.get("alias").toString();
        track.lat=Double.parseDouble(fbtrack.get("lat").toString());
        track.lon=Double.parseDouble(fbtrack.get("lon").toString());
        track.acu=Float.parseFloat(fbtrack.get("acu").toString());
        track.upd=Long.parseLong(fbtrack.get("upd").toString());
        return track;
    }


    public static Track getTrack(Map<String, Object> tracks,String trackId){

        Iterator<Object> it = tracks.values().iterator();
        while (it.hasNext()){
            Map<String, Object> fbtrack = (Map<String, Object>) it.next();
            return getTrack(trackId, fbtrack);
        }
        return null;
    }

    @Override
    public void onDestroy() {
        if (DEBUG) Log.d(TAG, "onDestroy");
        getMain().removePartnersFragment();
        super.onDestroy();
    }

    private MainActivity getMain() {
        return ((MainActivity)getActivity());
    }

} public class RingsFragment extends Fragment {

    public static final String TAG = RingsFragment.class.getSimpleName();

    private RecyclerView mRingsRecycler;
    private ListRingsAdapter mRingsAdapter;
    private TextView mEmptyMessage;
    private FloatingActionButton mAddRingFromContacts;
    private FloatingActionButton mAddRingFromQRCode;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_rings,container,false);


        mRingsRecycler= view.findViewById(R.id.rv_rings);
        GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 1);
        mRingsRecycler.setLayoutManager(gridLayoutManager);

        getMain().setFbPrimaryListener(onRingAddFromContactsListener);
        getMain().setFbSecondaryListener(onRingAddFromQRcodeListener);

        mRingsAdapter= new ListRingsAdapter();
        mRingsAdapter.setOnItemClickListener(onItemClickListener);
        mRingsAdapter.loadData(Storage.getRings(getActivity()));
        mRingsRecycler.setAdapter(mRingsAdapter);

        ItemTouchHelper.Callback callback = new ItemTouchHelperCallback(mRingsAdapter);
        ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
        touchHelper.attachToRecyclerView(mRingsRecycler);

        refreshUI();

        return view;
    }

    public void addRing(Ring ring) {

        Logger.d(TAG, "addRing: " + ring.toString());
        mRingsAdapter.addItem(0, ring);
        Storage.saveRing(getActivity(),ring);
        refreshUI();

    }

    private void refreshUI(){
        if(mRingsAdapter.getItemCount()>0){
            mRingsRecycler.setVisibility(View.VISIBLE);
        }else{
            mRingsRecycler.setVisibility(View.GONE);
        }

    }

    public class ItemTouchHelperCallback extends ItemTouchHelper.Callback {

        private final ItemTouchHelperAdapter mAdapter;

        public ItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
            mAdapter = adapter;
        }

        @Override
        public boolean isLongPressDragEnabled() {
            return true;
        }

        @Override
        public boolean isItemViewSwipeEnabled() {
            return true;
        }

        @Override
        public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {

            int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
            int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
            return makeMovementFlags(dragFlags, swipeFlags);

        }

        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
            Logger.d(TAG, "ItemTouchHelperCallback: onMove");
            return true;
        }

        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
            Logger.d(TAG, "ItemTouchHelperCallback: onSwiped: direction="+direction);
            int position = viewHolder.getAdapterPosition();
            if(direction==16) {
                Storage.removeRing(getActivity(), mRingsAdapter.getItem(position));
                mAdapter.onItemDismiss(position);
            }else if(direction==32){
                Ring ring = mRingsAdapter.getItem(position);
                boolean enable = !ring.isEnable();
                Storage.enableRing(getActivity(), ring, enable);
                mAdapter.onItemDisable(position,enable);
            }
            refreshUI();
        }

    }

    private MainActivity getMain() {
        return ((MainActivity)getActivity());
    }

    private AdapterView.OnItemClickListener onItemClickListener = new AdapterView.OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
            Logger.d(TAG, "OnItemClickListener => Clicked: " + position + ", index " + mRingsRecycler.indexOfChild(view));
        }
    };

    private View.OnClickListener onRingAddFromContactsListener = view -> {
        Logger.d(TAG, "onRingAddFromContactsListener");
        getMain().fabColapse();
        getMain().showAddContactsRingFragment();
    };
    private View.OnClickListener onRingAddFromQRcodeListener = view -> {
        Logger.d(TAG, "onRingAddFromQRcodeListener");
        getMain().fabColapse();
        getMain().showAddContactsRingFragment();
    };

    @Override
    public void onResume() {
        getMain().fabShow();
        super.onResume();
    }

    @Override
    public void onDestroy() {
        getMain().fabHide();
        super.onDestroy();
    }


} public class Storage {

    private static final String PREF_GENERAL_PANIC_ALERT = "lastPanic";
    private static final String PREF_SAVE_RINGS = "ringsSaved";
    private static final String PREF_SHARE_LOCATION = "shareLocationEnable";
    private static final String PREF_TRACK_ID = "trackId";
    private static final String PREF_TRACKING_TARGET = "trackingTarget";
    private static final String PREF_FIRST_INTRO = "firsIntro";
    private static final String PREF_SAVE_TRACKERS = "saveTrackers";
    private static final String PREF_CURRENT_ALIAS = "currentAlias";
    private static final String PREF_CURRENT_COLOR = "currentColor";

    public static void setLastPanicAlertDate(Context ctx, String time) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        SharedPreferences.Editor ed = prefs.edit();
        ed.putString(PREF_GENERAL_PANIC_ALERT, time);
        ed.commit();
    }

    public static String getLastPanicAlertDate(Context ctx) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        return prefs.getString(PREF_GENERAL_PANIC_ALERT, ctx.getString(R.string.no_panic_alert));
    }

    public static ArrayList<Ring> getRings(Context ctx) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
        String ringJson = preferences.getString(PREF_SAVE_RINGS, "");
        if (ringJson.equals("")) return new ArrayList<>();
        else {
            Type listType = new TypeToken<ArrayList<Ring>>() {
            }.getType();
            return new Gson().fromJson(ringJson, listType);
        }
    }

    public static void saveRings(Context ctx, ArrayList<Ring> rings) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString(PREF_SAVE_RINGS, new Gson().toJson(rings));
        editor.commit();
    }

    public static void saveRing(Context ctx, Ring ring) {
        ArrayList<Ring> rings = getRings(ctx);
        rings.add(ring);
        saveRings(ctx, rings);
    }

    public static void removeRing(Context ctx, Ring ring) {
        ArrayList<Ring> rings = getRings(ctx);
        Iterator<Ring> it = rings.iterator();
        while (it.hasNext()) {
            if (it.next().getName().equals(ring.getName())) it.remove();
        }
        saveRings(ctx, rings);
    }

    public static void enableRing(Context ctx, Ring ring, boolean enable) {
        ArrayList<Ring> rings = getRings(ctx);
        Iterator<Ring> it = rings.iterator();
        while (it.hasNext()) {
            Ring item = it.next();
            if (item.getName().equals(ring.getName())) item.setEnable(enable);
        }
        saveRings(ctx, rings);
    }

    public static void setShareLocationEnable(Context ctx, boolean shareLocation) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putBoolean(PREF_SHARE_LOCATION, shareLocation);
        editor.commit();
    }

    public static boolean isShareLocationEnable(Context ctx) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        return prefs.getBoolean(PREF_SHARE_LOCATION, false);
    }

    public static void setTrackId(Context ctx, String trackId) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString(PREF_TRACK_ID, trackId);
        editor.commit();
    }

    public static String getTrackId(Context ctx) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        return prefs.getString(PREF_TRACK_ID, null);
    }

    public static void setTargetTracking(Context ctx, String path) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString(PREF_TRACKING_TARGET, path);
        editor.commit();
    }

    public static String getTargetTracking(Context ctx) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        return prefs.getString(PREF_TRACKING_TARGET, null);
    }

    public static ArrayList<Ring> getRingsEnable(Context ctx) {
        ArrayList<Ring> rings = getRings(ctx);
        Iterator<Ring> it = rings.iterator();
        while (it.hasNext()) if (!it.next().isEnable()) it.remove();
        return rings;
    }

    public static boolean isFirstIntro(Context ctx) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        return prefs.getBoolean(PREF_FIRST_INTRO, true);
    }

    public static void setFirstIntro(Context ctx, boolean enable) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        SharedPreferences.Editor ed = prefs.edit();
        ed.putBoolean(PREF_FIRST_INTRO, enable);
        ed.commit();
    }

    public static ArrayList<Track> getTrackers(Context ctx) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
        String ringJson = preferences.getString(PREF_SAVE_TRACKERS, "");
        if (ringJson.equals("")) return new ArrayList<>();
        else {
            Type listType = new TypeToken<ArrayList<Track>>() {
            }.getType();
            return new Gson().fromJson(ringJson, listType);
        }
    }

    public static void saveTrackers(Context ctx,ArrayList<Track>trackers){
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ctx);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString(PREF_SAVE_TRACKERS, new Gson().toJson(trackers));
        editor.commit();
    }

    @Deprecated
    public static void addTracker(Context ctx, String trackId, String alias) {
        ArrayList<Track> trackers = getTrackers(ctx);
        trackers.add(new Track(trackId, alias));
        saveTrackers(ctx, trackers);
    }


    synchronized public static void addTracker(Context ctx, Track track) {
        ArrayList<Track> trackers = getTrackers(ctx);
        trackers.add(track);
        saveTrackers(ctx, trackers);
    }

    synchronized public static void updateTracker(Context ctx, Track track) {
        ArrayList<Track> trackers = getTrackers(ctx);
        Iterator<Track> it = trackers.iterator();
        while (it.hasNext()){
            Track currentTrack = it.next();
            if(currentTrack.trackId.equals(track.trackId)){
                trackers.remove(trackers.indexOf(currentTrack));
                trackers.add(track);
            }
        }
        saveTrackers(ctx, trackers);
    }

    public static boolean isOldTracker(Context ctx,String trackerId) {
        ArrayList<Track> trackers = getTrackers(ctx);
        Iterator<Track> it = trackers.iterator();
        while (it.hasNext())if(it.next().trackId.equals(trackerId))return true;
        return false;
    }

    public static String getCurrentAlias(Context ctx) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        return prefs.getString(PREF_CURRENT_ALIAS, "");
    }

    public static void setCurrentAlias(Context ctx, String alias){
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        SharedPreferences.Editor ed = prefs.edit();
        ed.putString(PREF_CURRENT_ALIAS, alias);
        ed.commit();
    }

    public static int getCurrentColor(Context ctx) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        return prefs.getInt(PREF_CURRENT_COLOR, Color.MAGENTA);
    }
} public class Contact {

    public String photoUri;

    public String name;

    public String phone;

    public Bitmap photo;

    public Contact(String name, String phone, Bitmap photo) {
        this.name=name;
        this.phone=phone;
        this.photo=photo;
    }


    public Contact(String name, String phone, String uri) {
        this.name=name;
        this.phone=phone;
        this.photoUri =uri;
    }


    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "name: "+name+" phone:"+phone;
    }

    public String getPhone() {
        return phone;
    }

    public Bitmap getPhoto() {
        return photo;
    }
} public class Partner {

    public String alias;

    public Bitmap avatar;


    public String last_update;

    public Partner(String alias, String last_update) {
        this.alias=alias;
        this.avatar=avatar;
        this.last_update=last_update;
    }

    public String getAlias() {
        return alias;
    }

    public String getLast_update() {
        return last_update;
    }

    @Override
    public String toString() {
        return "alias: "+alias;
    }

} public class Track {

    public String trackId;


    public String alias;

    public int color;

    private boolean enable;

    private String lastUpdate;

    public double lat;

    public double lon;

    public float acu;

    public long upd;

    public Track(String trackId, String alias) {
        this.trackId = trackId;
        this.alias = alias;
    }

    public Track() {

    }

    public int getColor() {
        return color;
    }

    public void setColor(int color) {
        this.color = color;
    }

    public void setEnable(boolean enable) {
        this.enable = enable;
    }

    public boolean isEnable() {
        return enable;
    }

    @Override
    public String toString() {
        return "track: " + trackId + " alias:" + alias;
    }

    public String getLastUpdate() {
        // TODO: set last update on track
        lastUpdate = "Wednesday 23, 17:25";
        return lastUpdate;
    }
} public class HardwareButtonReceiver extends BroadcastReceiver {
    public static final String TAG = HardwareButtonReceiver.class.getSimpleName();
    private static final boolean DEBUG = Config.DEBUG;

    @Override
    public void onReceive(Context context, Intent intent) {

        startScheduleService(context,Config.DEFAULT_INTERVAL);

    }

    public static void startScheduleService(Context context,long repeatTime){

        if(DEBUG) Log.d(TAG, "HardwareButtonReceiver  startScheduleService");

        AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent(context, StartStatusServiceReceiver.class);
        PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,
                PendingIntent.FLAG_CANCEL_CURRENT);
        Calendar cal = Calendar.getInstance();

        // Start x seconds after boot completed
        cal.add(Calendar.SECOND, Config.TIME_AFTER_START);

        service.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), repeatTime, pending);
    }

    public static void stopSheduleService(Context context){

        if(DEBUG) Log.d(TAG, "HardwareButtonReceiver  stopSheduleService:");

        AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent i = new Intent(context, StartStatusServiceReceiver.class);
        PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,
                PendingIntent.FLAG_CANCEL_CURRENT);
        service.cancel(pending);
    }
} public class HardwareButtonService extends Service implements GoogleApiClient.ConnectionCallbacks,
                                    GoogleApiClient.OnConnectionFailedListener, LocationListener {

    public static final String TAG = HardwareButtonService.class.getSimpleName();

    private String result;
    private boolean isFirstTime, isSendMesagge, locationActivated;
    public static boolean serviceRunning, countTimer;
    private static int countStart;
    private HardwareButtonReceiver hwButtonReceiver;
    private Handler handlerTime;
    private ResultReceiver resultReceiver;
    private LocationRequest mLocationRequest;
    private GoogleApiClient mGoogleApiClient;
    private Location lastLocation;
    private SendSMSMessage smsTask;
    private BroadcastReceiver mReceiver;
    private final IBinder mBinder = new HardwareButtonServiceBinder();


    @Override
    public void onCreate() {
        super.onCreate();
        serviceRunning = locationActivated = false;
        countTimer = true;
        countStart = -1;
        handlerTime = new Handler();
        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        hwButtonReceiver = new HardwareButtonReceiver();
        registerReceiver(mReceiver, filter);
        lastLocation = null;
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (isFirstTime) {
            isFirstTime = false;
            serviceRunning = true;
            locationActivated = false;
        }
        try {
            resultReceiver = intent.getParcelableExtra("receiver");
            //Check for the number of times the button has been pressed
            if (countStart >= 5) {
                Logger.i(TAG, "=== 5 Intents");
                countStart = -1;
                countTimer = true;
                startLocationService();
            }
            else {
                //restarting counters after 5 seconds
                countStart += 1;
                if (countTimer) {
                    countTimer = false;
                    handlerTime.postDelayed(runnable, Config.RESTART_HARDWARE_BUTTON_TIME);
                }
            }
        } catch (Exception e) {
            Logger.i(TAG, "=== No results available." + e);
        }

        return super.onStartCommand(intent, flags, startId);
    }


    public void sendAlertSMS() {
        startLocationService();
        startSMSTask();
    }


    /*
    * Starts the API for location service if its not activated
    */
    private void startLocationService() {
        if (mGoogleApiClient == null || !mGoogleApiClient.isConnected()) {
            Logger.i(TAG, "=== Starting geolocalization service: UNCONNECTED -> CONECTED");
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
            mGoogleApiClient.connect();
        }
        else
            Logger.i(TAG, "=== Starting geolocalization service: ALREADY CONNECTED");

        locationActivated = true;
    }

    /**
     * Stops the location service if its activated
     */
    private void stopLocationService() {
        if (mGoogleApiClient != null || mGoogleApiClient.isConnected()) {
            mGoogleApiClient.disconnect();
            Logger.i(TAG, "=== Stopping geolocalization service: CONNECTED -> UNCONNECTED");
        }
        else
            Logger.i(TAG, "=== Stopping geolocalization service: ALREADY CONNECTED");

        locationActivated = false;
    }

    /*
     * Setting the service quality
     */
    private void setupLocationForMap() {
        long fastUpdate = Config.DEFAULT_INTERVAL_FASTER;
        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        mLocationRequest.setInterval(Config.DEFAULT_INTERVAL);
        mLocationRequest.setFastestInterval(fastUpdate);
    }

    /*
     * Starts the asyncronous task to send the sms messages
     */
    private void startSMSTask() {
        if (smsTask == null || smsTask.getStatus() == AsyncTask.Status.FINISHED) {
            Logger.i(TAG, "=== smsTask is null or finished. Starting task ");
            smsTask = new SendSMSMessage();
            smsTask.execute();
        }
    }

    /**
     * Phone vibration
     *
     * @param time time for vibration
     */
    public void vibrate(long time) {
        Vibrator v = (Vibrator) this.getSystemService(Context.VIBRATOR_SERVICE);
        v.vibrate(time);
    }

    /**
     * Gets the battery level
     *
     * @return battery level
     */
    public int getBatteryLevel() {
        Intent i = new ContextWrapper(this).registerReceiver(null,
                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
        return i.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        try {
            serviceRunning = false;
            if(hwButtonReceiver!=null){
                unregisterReceiver(hwButtonReceiver);
            }
        } catch (Exception e) {
            Log.e(TAG,"unregisterReceiver Exception: "+e.getMessage());
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    @Override
    public void onConnected(Bundle bundle) {
        locationActivated = true;
        mLocationRequest = LocationRequest.create();
        setupLocationForMap();
        LocationServices.FusedLocationApi
                .requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);

        if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
            this.lastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        }

    }

    @Override
    public void onConnectionSuspended(int i) {
        locationActivated = false;
    }

    @Override
    public void onLocationChanged(Location location) {
        this.lastLocation = location;
        if (countTimer) {
            startSMSTask();
            vibrate(Config.VIBRATION_TIME_SMS);
            stopLocationService();
        }
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        locationActivated = false;
    }

    /*
     * thread for restarting values
     */
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            //restart counters
            countStart = -1;
            countTimer = true;
        }
    };

    /*
     * Inner class to handle SMS mesaages for alert sms messages.
     * The task is started when AlertButton (software) is pressed
     * or the power button is pressed 4 or more times.
     */
    public class SendSMSMessage extends AsyncTask<Void, Void, Void> {
        @Override
        protected void onCancelled() {
        }

        @Override
        protected Void doInBackground(Void... params) {
            ArrayList<String> numbers = new ArrayList<String>();
            String location = "";
            result = "OK";

            if (lastLocation != null) {
                location = getString(R.string.map_provider)
                        + lastLocation.getLatitude() + ","
                        + lastLocation.getLongitude() + "\n";
            }

            Logger.i(TAG, "=== Localization : " + location);

            numbers.addAll(contactsRingNumbers());

            Logger.i(TAG, "=== Contacts to notify : " + numbers.size());

            if (numbers.size() == 0) {
                result = getString(R.string.no_configured_rings);
                Logger.i(TAG,"=== No rings found");
            }
            else {
                isSendMesagge = true;
                int fails = 0, nonValid = 0;
                String message = getString(R.string.tracking_SMS_message);
                message = message.replace("%map", location).replace("%battery",
                        getBatteryLevel() + "%");

                for (int i = 0; i < numbers.size(); i++) {
                    try {
                        String number = numbers.get(i).replaceAll("\\D+", "");
                        if (number != null && number.length() > 0) {
                            sendSMS(number, message);
                            if(!result.equalsIgnoreCase("OK")) {
                                fails ++;
                                Logger.i(TAG, "=== Error sending SMS to: " + numbers.get(i));
                            }
                        }
                        else{
                            nonValid ++;
                            fails ++;
                        }
                    } catch (Exception ex) {
                        Logger.i(TAG, "=== Error sending SMS to: " + numbers.get(i) + ex.getMessage());
                        fails ++;
                    }
                }
                if (fails > 0) {
                    result += getString(R.string.any_sms_sent);
                    result = result.replace("%count1", String.valueOf(fails));
                    result += String.valueOf(numbers.size());
                    Logger.i(TAG,"=== Error sending SMS to : " + numbers.toString());
                }
                if (nonValid > 0){
                    result += getString(R.string.tracking_invalid_contac_numbers);
                    result.replace("%count", String.valueOf(nonValid));
                }
                Logger.i(TAG, "=== " + result);
            }
            try {
                Logger.i(TAG, "=== Finalizing smsTask ");
                this.finalize();
            } catch (Throwable throwable) {
                Logger.i(TAG, "=== Error finalizing the smsTask ");
                throwable.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void r) {
            super.onPostExecute(r);
            isSendMesagge = false;

            Logger.i(TAG,"=== PostExecute " );

            if (result.equalsIgnoreCase("OK")) {
                //TODO: Check if is necesary to save the datetime for the last alarm sent
                String currentDateandTime = UITools.getDateFormatTrack(Calendar.getInstance());
                Storage.setLastPanicAlertDate(getApplicationContext(),
                        currentDateandTime);
                /*Tools.showToast(getApplicationContext(), getString(
                        R.string.panic_alert_sent));*/
                UITools.showToast(getBaseContext(), getString(R.string.sms_sent));
            }
            else {
                UITools.showToast(getApplicationContext(), result);
            }
        }

        private void sendSMS(String mobileNumber, String message) {
            SmsManager sms = SmsManager.getDefault();
            try {
                ArrayList<String> parts = sms.divideMessage(message);
                int numParts = parts.size();
                Context context = getApplicationContext();
                ArrayList<PendingIntent> sent = new ArrayList<PendingIntent>(numParts);
                ArrayList<PendingIntent> delivered = new ArrayList<PendingIntent>(numParts);

                for (int i = 0; i < numParts; i++) {
                    PendingIntent sentIntent = PendingIntent.getBroadcast(context,
                            0, new Intent("SENT"), 0);
                    Logger.i(TAG,"=== building intents for SMS " );

                    context.registerReceiver(new BroadcastReceiver() {
                        @Override
                        public void onReceive(Context arg0, Intent arg1) {
                            result = "FAIL";
                            Logger.i(TAG,"=== Intent OnReceive Sent " + getResultCode() );
                            switch (getResultCode()) {
                                case Activity.RESULT_OK:
                                    result = "OK";
                                    Logger.i(TAG,"=== " +  getString(R.string.sms_sent));
                                    break;
                                case SmsManager.RESULT_ERROR_NO_SERVICE:
                                    result = getString(R.string.sms_not_sent);
                                    Logger.i(TAG,"=== " +  getString(R.string.sms_not_sent));
                                    break;
                                case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                                    result = getString(R.string.sms_generic_fail);
                                    Logger.i(TAG,"=== " +  getString(R.string.sms_generic_fail));
                                    break;
                                case SmsManager.RESULT_ERROR_NULL_PDU:
                                    result = getString(R.string.sms_null_pdu);
                                    Logger.i(TAG,"=== NULL PDU ");
                                    break;
                                case SmsManager.RESULT_ERROR_RADIO_OFF:
                                    result = getString(R.string.sms_radio_off);
                                    Logger.i(TAG,"=== Error. Airplane Mode ");
                                    break;
                            }
                        }
                    }, new IntentFilter("SENT"));

                    sent.add(sentIntent);
                    PendingIntent deliveredIntent = PendingIntent.getBroadcast(
                            context, 0, new Intent("DELIVERED"), 0);
                    context.registerReceiver(new BroadcastReceiver() {
                        @Override
                        public void onReceive(Context arg0, Intent arg1) {
                            Logger.i(TAG,"=== Intent OnReceive Delivered "  + getResultCode());
                            switch (getResultCode()) {
                                case Activity.RESULT_OK:
                                    UITools.showToast(getBaseContext(), getString(R.string.sms_delivered));
                                    Logger.i(TAG,"=== SMS OK  ");
                                    break;
                                case Activity.RESULT_CANCELED:
                                    UITools.showToast(getBaseContext(), getString(R.string.sms_canceled));
                                    Logger.i(TAG,"=== SMS Canceled  " );
                                    break;
                            }
                        }
                    }, new IntentFilter("DELIVERED"));
                    delivered.add(deliveredIntent);
                }

                sms.sendMultipartTextMessage(mobileNumber, null, parts, sent, delivered);
                Logger.i(TAG,"=== Message  " + message + " sent to " + mobileNumber);
            }
            catch (Exception e) {
                Logger.i(TAG,"=== Error sending message to " + mobileNumber + " " + e.getMessage());
            }
        }

        private ArrayList contactsRingNumbers() {
            List<Contact> contacts;
            ArrayList<Ring> enableRings = Storage.getRingsEnable(getApplicationContext());
            ArrayList<String> numbers = new ArrayList<>();

            if(enableRings == null)
                return null;

            for (Ring ring: enableRings) {
                contacts = ring.getContacts();
                for(Contact c : contacts){
                    Logger.i(TAG, "Contact Number: " + c.getPhone());
                    numbers.add(c.getPhone().trim());
                }
            }
            Logger.i(TAG, "=== Number of contacts to notify: " + numbers.size());
            return numbers;
        }
    }

    public class HardwareButtonServiceBinder extends Binder {
        public HardwareButtonService getService() {
            return HardwareButtonService.this;
        }
    }

} public class TrackLocationService extends Service implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener{

    public static final String TAG = TrackLocationService.class.getSimpleName();
    private static final boolean DEBUG = Config.DEBUG;
    public static final String TRACK_SERVICE_CONNECT = "brodcast_onfirebase_connected";
    public static final String KEY_TRACKID = "key_trackId";


    private GoogleApiClient mGoogleApiClient;
    private Location location;
    private LocationRequest locationRequest;
    private String trackId;

    @Override
    public void onCreate(){
        startLocationService();
    }

    @Override
    public int onStartCommand(Intent intent,  int flags, int startId){
        if(DEBUG) Log.i(TAG, "=== OnStartCommand ");
        this.trackId = Storage.getTrackId(this);
        sendBroadcast(new Intent(TRACK_SERVICE_CONNECT));
        return Service.START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;

    }

    public void onDestroy(){
        stopLocationService();
        if(DEBUG)Log.i(TAG, "=== onDestroy");
    }


    public void stopLocationService() {
        if(DEBUG)Log.i(TAG, "=== stopLocationService");
        if (mGoogleApiClient!=null&&mGoogleApiClient.isConnected()) {
            mGoogleApiClient.disconnect();
        }
    }

    private void sendDataFrame(Location location) {
        if(DEBUG)Log.i(TAG, "=== Sending Tracking to server");
        Track track = new Track();
        track.lat=location.getLatitude();
        track.lon=location.getLongitude();
        track.acu=location.getAccuracy();
        track.upd=location.getTime();

        track.alias=Storage.getCurrentAlias(this);
        track.color=Storage.getCurrentColor(this);
    }

    private void setupLocationForMap() {
        long fastUpdate = Config.DEFAULT_INTERVAL_FASTER;
        locationRequest = LocationRequest.create();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(Config.DEFAULT_INTERVAL);
        locationRequest.setFastestInterval(fastUpdate);
    }

    private synchronized void startLocationService() {
        if( mGoogleApiClient == null || !mGoogleApiClient.isConnected()) {
            if(DEBUG)Log.i(TAG, "=== Starting LocationServices: NON CONECTED -> CONECTED");
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
            mGoogleApiClient.connect();
        }
        else
            if(DEBUG)Log.i(TAG, "=== GPS service started: CONECTED");
    }

    @Override
    public void onConnected(Bundle bundle) {

        setupLocationForMap();

        if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
            startLocationUpdates();
        }

    }

    protected void startLocationUpdates() {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this);
    }

    @Override
    public void onConnectionSuspended(int i) {
        if(DEBUG)Log.i(TAG, "=== Connection suspended");
    }

    @Override
    public void onLocationChanged(Location location) {
        this.location = location;
        if(DEBUG)Log.i(TAG, "=== onLocationChanged: Latitude: " + this.location.getLatitude() + " Longitude: " + this.location.getLongitude());
        sendDataFrame(location);
    }


    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        if(DEBUG)Log.i(TAG, "=== Connection Fail");
    }


}
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.view.KeyEvent;
import android.view.View;
import com.crashlytics.android.Crashlytics;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.hpsaturn.tools.DeviceUtil;
import com.hpsaturn.tools.Logger;
import com.hpsaturn.tools.UITools;
import com.livinglifetechway.quickpermissions.annotations.WithPermissions;
import org.parallelzero.hancel.Fragments.AboutFragment;
import org.parallelzero.hancel.Fragments.AliasFragment;
import org.parallelzero.hancel.Fragments.ConfirmDialogFragment;
import org.parallelzero.hancel.Fragments.ContactsRingFragment;
import org.parallelzero.hancel.Fragments.InputDialogFragment;
import org.parallelzero.hancel.Fragments.MainFragment;
import org.parallelzero.hancel.Fragments.MapPartnersFragment;
import org.parallelzero.hancel.Fragments.MapTasksFragment;
import org.parallelzero.hancel.Fragments.RingsFragment;
import org.parallelzero.hancel.System.Storage;
import org.parallelzero.hancel.models.Contact;
import org.parallelzero.hancel.models.Partner;
import org.parallelzero.hancel.models.Track;
import org.parallelzero.hancel.services.HardwareButtonReceiver;
import org.parallelzero.hancel.services.HardwareButtonService;
import org.parallelzero.hancel.services.TrackLocationService;
import java.util.ArrayList;
import java.util.Iterator;
import info.guardianproject.panic.PanicResponder;
import io.fabric.sdk.android.Fabric;
package org.parallelzero.hancel;







public class MainActivity extends BaseActivity implements BaseActivity.OnPickerContactUri, OnMapReadyCallback, View.OnKeyListener {

    public static final String TAG = MainActivity.class.getSimpleName();

    private OnTrackServiceConnected fbConnectReceiver;

    public MapTasksFragment tasksMap;
    private RingsFragment mRingsFragment;
    private ContactsRingFragment mContactsRingFragment;
    private MainFragment mMainFragment;
    private AboutFragment mAboutFragment;
    private MapPartnersFragment mPartnersFragment;
    private AliasFragment mAliasFragment;

    private HardwareButtonService mHardwareButtonService;
    private boolean mBound;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Fabric.with(MainActivity.this, new Crashlytics());

        startIntro();
        initDrawer();
        fabHide();
        String trackId = DeviceUtil.getAndroidDeviceId(MainActivity.this);
        Storage.setTrackId(this, trackId);