public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final String TAG = HomeAdapter.class.getSimpleName();

    private static final int TYPE_HEADER = 0;
    private static final int TYPE_ITEM = 1;
    private static final int TYPE_FOOTER = 2;

    public OnItemClickListener mItemClickListener;
    private ArrayList<LineStop> favoriteStopLine;
    private FragmentActivity context;

    private FavHomeView favHomeView;
    private SearchView searchView;

    public HomeAdapter(ArrayList<LineStop> stopLines, FragmentActivity context, FavHomeView favHomeView, SearchView searchView) {
        this.favoriteStopLine = stopLines;
        this.context = context;
        this.favHomeView = favHomeView;
        this.searchView = searchView;
    }

    public interface OnItemClickListener {
        void onItemClick(View view, int position);
    }

    public void SetOnItemClickListener(final OnItemClickListener mItemClickListener) {
        this.mItemClickListener = mItemClickListener;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_HEADER) {
            View v = searchView.getView(parent);
            return new ViewHolderCustom(v);
        } else if (viewType == TYPE_ITEM) {
            View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_card_home_line_stop, parent, false);
            return new ViewHolder(v);
        } else if (viewType == TYPE_FOOTER) {
            View v = favHomeView.getView(parent);
            return new ViewHolderCustom(v);
        }
        throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holderParam, int position) {
        if (holderParam instanceof ViewHolderCustom) {
            return;
        }
        ViewHolder holder = (ViewHolder) holderParam;
        LineStop lineStop = favoriteStopLine.get(position -1);
        StopZone s = lineStop.getStopZone();
        Line l = lineStop.getLine();

        holder.title.setText(s.getName() + " - Ligne " + l.getLineNum());
        holder.recyclerView.setHasFixedSize(true);
        RecyclerView.LayoutManager layoutManager = new org.solovyev.android.views.llm.LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
        holder.recyclerView.setLayoutManager(layoutManager);
        holder.recyclerView.setItemAnimator(new DefaultItemAnimator());
        AllDirectionStopLine adapter = new AllDirectionStopLine(s.getStops(l), context);
        final StopZone finalS = s;
        adapter.SetOnItemClickListener(new AllDirectionStopLine.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Intent intent = new Intent(context, OneStopActivity.class);
                Bundle bundle = new Bundle();
                bundle.putInt("stop_zone_id", finalS.getID());
                intent.putExtras(bundle);
                context.startActivity(intent);
                context.overridePendingTransition(R.anim.slide_from_right, R.anim.fade_scale_out);
            }
        });
        holder.recyclerView.setAdapter(adapter);
    }

    @UiThread
    public void dataSetChanged() {
        notifyDataSetChanged();
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0) {
            return TYPE_HEADER;
        } else if (position == getItemCount()-1) {
            return TYPE_FOOTER;
        } else {
            return TYPE_ITEM;
        }
    }

    @Override
    public int getItemCount() {
        return favoriteStopLine.size() + 2;
    }

    public class ViewHolderCustom extends RecyclerView.ViewHolder {

        public ViewHolderCustom(View itemView) {
            super(itemView);
        }
    }

    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

        public TextView title;
        public RecyclerView recyclerView;
        public ImageView menu;

        public ViewHolder(View v) {
            super(v);
            title = (TextView) itemView.findViewById(R.id.title);
            recyclerView = (RecyclerView) itemView.findViewById(R.id.times);
            menu = (ImageView) itemView.findViewById(R.id.menu);
            menu.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if (mItemClickListener != null) {
                mItemClickListener.onItemClick(v, getPosition());
            }
        }

    }
} public class Data {

    private static final String TAG = Data.class.getSimpleName();

    private DisruptEventHandler disruptEventHandler;
    private ReportEvent reportEvent;
    private RealTimes realTimes;
    private TamMap map;
    private RealTimeToUpdate toUpdate;

    private static Data data;

    private Data() {
        data = this;
    }

    public void init(Context context) {
        reportEvent = new ReportEvent(context);
        disruptEventHandler = new DisruptEventHandler(context);
        realTimes = new RealTimes(context);
        map = new TamMap(context);
    }

    public static synchronized Data getData() {
        if (data == null) {
            return new Data();
        } else {
            return data;
        }
    }

    public void update() {
        if (toUpdate != null) {
            if (toUpdate.isLine()) {
                realTimes.updateLine(toUpdate.getLine());
            } else {
                realTimes.updateStops(toUpdate.getStops());
            }
        }
        reportEvent.getReports();
        //disruptEventHandler.getReports();
    }

    public DisruptEventHandler getDisruptEventHandler() {
        return disruptEventHandler;
    }

    public TamMap getMap() {
        return map;
    }

    public void setToUpdate(RealTimeToUpdate toUpdate) {
        this.toUpdate = toUpdate;
        update();
    }

    public RealTimes getRealTimes() {
        return realTimes;
    }

    public ReportEvent getReportEvent() {
        return reportEvent;
    }
} public class FavoriteStopLine {

    private static final String TAG = FavoriteStopLine.class.getSimpleName();

    private ArrayList<LineStop> favoriteStopLine;
    private Context context;

    public FavoriteStopLine(Context c) {
        context = c;
        getFromPref();
    }

    private void getFromPref() {
        SharedPreferences defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);

        favoriteStopLine = new ArrayList<>();
        for (String info : defaultSharedPreferences.getStringSet(TAG, new HashSet<String>())) {
            String[] infos = info.split("<>");
            StopZone s = Data.getData().getMap().getStopZoneById(Integer.parseInt(infos[0]));
            Line l = Data.getData().getMap().getLineByNum(Integer.parseInt(infos[1]));
            favoriteStopLine.add(new LineStop(s, l));
        }
    }

    // STOP LINES

    public void addLineStop(Line l, StopZone s) {
        favoriteStopLine.add(new LineStop(s, l));
        sortAndPush();
    }

    public void removeLineStop(int position) {
        favoriteStopLine.remove(position);
        sortAndPush();
    }

    public ArrayList<LineStop> getFavStopLines() {
        getFromPref();
        return new ArrayList<>(favoriteStopLine);
    }

    public ArrayList<Stop> getToUpdate() {
        ArrayList<Stop> toUpdate = new ArrayList<>();
        for (LineStop lineStop : getFavStopLines()) {
            toUpdate.addAll(lineStop.getStops());
        }
        return toUpdate;
    }

    private void sortAndPush() {
        pushToPref();
    }

    public void pushToPref() {
        SharedPreferences defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
        SharedPreferences.Editor editor = defaultSharedPreferences.edit();

        ArrayList<String> favLineStop = new ArrayList<>();
        for (LineStop lineStop : favoriteStopLine) {
            favLineStop.add(lineStop.getStopZone().getID() + "<>" + lineStop.getLine().getLineNum());
        }

        editor.putStringSet(TAG, new HashSet<>(favLineStop));
        editor.commit();
    }
} public class Line {
    private String shortName;
    private int id;
    private int tam_id;
    private int cityway_id;
    private int urbanLine;
    private ArrayList<Direction> directions;

    private ArrayList<DisruptEvent> disruptEventList;

    public Line(String shortName, int id, int tamID, int citywayID, int urbanLine) {
        this.shortName = shortName;
        this.id = id;
        this.tam_id = tamID;
        this.cityway_id = citywayID;
        this.urbanLine = urbanLine;
        this.directions = new ArrayList<>();
        this.disruptEventList = new ArrayList<>();
    }

    // Get
    public Direction getRoute(String direction){
        for (int i = 0; i< directions.size(); i++){
            if (directions.get(i).equals(direction)) {
                return directions.get(i);
            }
        }
        return null;
    }

    public int getTam_id() {
        return tam_id;
    }

    public int getCityway_id() {

        return cityway_id;
    }

    public int getUrbanLine() {

        return urbanLine;
    }

    @Override
    public String toString() {
        return "Line{" +
                "shortName='" + shortName + '\'' +
                ", id=" + id +
                ", tam_id=" + tam_id +
                ", cityway_id=" + cityway_id +
                ", directions=" + directions +
                ", disruptEventList=" + disruptEventList +
                '}';
    }

    public int getId() {
        return id;
    }

    public ArrayList<Direction> getDirections() {
        return this.directions;
    }

    public void addRoute(Direction r) {
        this.directions.add(r);
    }

    public int getDirectionsCount(){
        return this.directions.size();
    }

    public String getShortName(){
        return this.shortName;
    }

    public int getLineNum(){
        return this.id;
    }

    public ArrayList<DisruptEvent> getDisruptEventList() {
        return disruptEventList;
    }

    public void removeDisruptEvent(DisruptEvent event) {
        this.disruptEventList.remove(event);
    }

    public void addDisruptEvent(DisruptEvent event) {
        this.disruptEventList.add(event);
    }
} public class RealTimeToUpdate {
    private boolean isLine;
    private Line line;
    private ArrayList<Stop> stops;


    public boolean isLine() {
        return isLine;
    }

    public Line getLine() {
        return line;
    }

    public ArrayList<Stop> getStops() {
        return stops;
    }


    public RealTimeToUpdate(ArrayList<Stop> stops) {
        this.stops = stops;
        isLine = false;
    }

    public RealTimeToUpdate(Line line) {
        this.line = line;
        isLine = true;
    }
} public class MessageUpdate {
    public enum Type {
        TIMES_UPDATE,
        LINES_UPDATE,
        EVENT_UPDATE,
        REPORT_UPDATE
    }

    public final Type type;

    public MessageUpdate(Type type) {
        this.type = type;
    }
} public class StopZone {
    private int _id;
    private int cityway_id;
    private int tam_id;
    private String name;
    private String search_name;
    private ArrayList<Line> lines;
    private ArrayList<Stop> stops;

    private Location location;
    private ArrayList<Report> reportList;
    private float distanceFromUser;

    public StopZone(String name, int _id, int tam_id, int cityway_id, String search_name, double lat, double lon){
        this.lines = new ArrayList<>();
        this.reportList = new ArrayList<>();
        this.name = name;
        this.cityway_id = cityway_id;
        this._id = _id;
        this.tam_id = tam_id;
        this.search_name = search_name;
        this.location = new Location(name);
        this.location.setLongitude(lon);
        this.location.setLatitude(lat);
        this.stops = new ArrayList<>();
    }

    public void addLine(Line line) {
        if (!this.lines.contains(line)) {
            this.lines.add(line);
        }
    }

    public void addStop(Stop stop) {
        this.stops.add(stop);
    }

    public String getName() {
        return name;
    }

    public ArrayList<Line> getLines() {
        return this.lines;
    }

    public int getID() {
        return this._id;
    }

    public void addReport(Report report) {
        this.reportList.add(report);
    }

    public ArrayList<Report> getReports() {
        ArrayList<Report> res = new ArrayList<>();
        Calendar date = Calendar.getInstance();
        for (Report r : this.reportList) {
            if (r.isValid(date)) res.add(r);
        }
        Collections.reverse(res); // the last is the oldest now.
        return res;
    }

    public void removeReport(Report rep) {
        this.reportList.remove(rep);
    }

    public void calcDistanceFromUser(Location user) {
        distanceFromUser = user.distanceTo(this.location);
    }

    public String getNormalisedName() {
        return search_name;
    }

    public float getDistanceFromUser() {
        return distanceFromUser;
    }

    public ArrayList<Stop> getStops(Line line) {
        ArrayList<Stop> res = new ArrayList<>();
        for (Stop stop : stops) {
            if (stop.getDirection().getLine().getCityway_id() == line.getCityway_id()) {
                res.add(stop);
            }
        }
        return res;
    }

    public ArrayList<Stop> getStops() {
        return stops;
    }

    @Override
    public String toString() {
        return "StopZone{" +
                "name='" + name + '\'' +
                ", lines=" + lines +
                ", stops=" + stops +
                '}';
    }
} public class UpdateRunnable implements Runnable {

    private Handler handler = new Handler();

    private static final int TIME = 30000; // 30 sec

    @Override
    public void run() {
        Data.getData().update();
        handler.postDelayed(this, TIME);
    }

    public void stop() {
        handler.removeCallbacks(this);
    }
} public class FavHomeView {

    private LinearLayout favLayout;
    private RecyclerView favStopRecyclerView;
    private FavWelcomeAdapter favStopAdapter;
    private FavoriteStops favoriteStops;

    public FragmentActivity context;

    public interface AddStopLine {
        void update(StopZone stop, Line line);
    }

    public AddStopLine updateStopLine;

    public void setUpdateStopLine(AddStopLine addStopLine) {
        this.updateStopLine = addStopLine;
    }

    public FavHomeView(FragmentActivity context) {
        this.context = context;
        favoriteStops = new FavoriteStops(context);
    }

    public View getView(ViewGroup parent) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.footer_home, parent, false);

        favLayout = (LinearLayout) view.findViewById(R.id.fav_stop_recycler);
        LinearLayout linearLayout = (LinearLayout) favLayout.findViewById(R.id.progress);
        linearLayout.setVisibility(View.GONE);
        TextView textView = (TextView) favLayout.findViewById(R.id.empty_view);
        textView.setText(context.getString(R.string.no_favorite_stop));


        favStopRecyclerView = (RecyclerView) favLayout.findViewById(R.id.recycler_view);
        favStopRecyclerView.setHasFixedSize(false);

        RecyclerView.LayoutManager layoutManagerFav = new org.solovyev.android.views.llm.LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
        favStopRecyclerView.setLayoutManager(layoutManagerFav);
        favStopRecyclerView.setItemAnimator(new DefaultItemAnimator());

        if (favoriteStops.getFavoriteStop().size() == 0) {
            textView.setVisibility(View.VISIBLE);
            favStopRecyclerView.setVisibility(View.GONE);
        } else {
            favStopAdapter = new FavWelcomeAdapter(favoriteStops.getFavoriteStop());
            favStopRecyclerView.setAdapter(favStopAdapter);
            favStopAdapter.SetOnItemClickListener(new FavWelcomeAdapter.OnItemClickListener() {

                @Override
                public void onItemClick(View v, int position) {
                    selectitem(favoriteStops.getFavoriteStop().get(position));
                }
            });

            favStopAdapter.SetOnMenuClickListener(new FavWelcomeAdapter.OnMenuClickListener() {
                @Override
                public void onItemClick(View v, final int position) {
                    //Creating the instance of PopupMenu
                    PopupMenu popup = new PopupMenu(context, v);
                    //Inflating the Popup using xml file
                    popup.getMenuInflater().inflate(R.menu.add_to_home, popup.getMenu());

                    //registering popup with OnMenuItemClickListener
                    popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem item) {

                            ArrayList<CharSequence> lines = new ArrayList<>();
                            for (Line l : favoriteStops.getFavoriteStop().get(position).getLines()) {
                                lines.add("Ligne " + l.getLineNum());
                            }
                            CharSequence[] lineString = lines.toArray(new CharSequence[lines.size()]);

                            MaterialDialog dialog = new MaterialDialog.Builder(context)
                                    .title(R.string.line_choice)
                                    .items(lineString)
                                    .itemsCallback(new MaterialDialog.ListCallback() {
                                        @Override
                                        public void onSelection(MaterialDialog dialog, View view, int which, CharSequence text) {
                                            StopZone s = favoriteStops.getFavoriteStop().get(position);
                                            Line l = s.getLines().get(which);
                                            updateStopLine.update(s, l);
                                            dialog.dismiss();
                                        }
                                    }).build();
                            dialog.show();
                            return true;
                        }
                    });

                    popup.show();
                }
            });
        }
        return view;
    }

    public void selectitem(StopZone s){
        Intent intent = new Intent(context, OneStopActivity.class);
        Bundle bundle = new Bundle();
        bundle.putInt("stop_zone_id", s.getID());
        intent.putExtras(bundle);
        context.startActivity(intent);
        context.overridePendingTransition(R.anim.slide_from_right, R.anim.fade_scale_out);
    }


} public class SearchView {

    private static final String TAG = SearchView.class.getSimpleName();

    public FragmentActivity context;
    private RecyclerView researchRecyclerView;
    private SeachResultAdapter researchAdapter;

    private ArrayList<StopZone> searchStop;
    private EditText search;

    public SearchView(FragmentActivity context) {
        this.context = context;
    }

    public View getView(ViewGroup parent) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.header_home, parent, false);
        RecyclerView.LayoutManager layoutManager = new org.solovyev.android.views.llm.LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);

        researchRecyclerView = (RecyclerView) view.findViewById(R.id.result);
        researchRecyclerView.setLayoutManager(layoutManager);
        researchRecyclerView.setItemAnimator(new DefaultItemAnimator());
        researchRecyclerView.setHasFixedSize(false);
        researchRecyclerView.swapAdapter(null, true);
        search = (EditText) view.findViewById(R.id.search_text);
        search.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                    new SearchAsync().execute(search.getText().toString());
                    return true;
                }
                return false;
            }
        });
        search.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean b) {
                search.setCursorVisible(b);
            }
        });

        search.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (s.toString().length() == 0) {
                    researchRecyclerView.swapAdapter(null, true);
                } else {
                    new SearchAsync().execute(s.toString());
                }
            }
        });
        return view;
    }

    public void selectitem(StopZone s){
        Intent intent = new Intent(context, OneStopActivity.class);
        Bundle bundle = new Bundle();
        bundle.putInt("stop_zone_id", s.getID());
        intent.putExtras(bundle);
        context.startActivity(intent);
        context.overridePendingTransition(R.anim.slide_from_right, R.anim.fade_scale_out);
    }

    private class SearchAsync extends AsyncTask<String, String, ArrayList<StopZone>> {
        protected ArrayList<StopZone> doInBackground(String... strings) {
            String s = strings[0];
            return Data.getData().getMap().searchInStops(s,3);
        }

        protected void onPostExecute(ArrayList<StopZone> stops) {
            searchStop = stops;
            researchAdapter = new SeachResultAdapter(searchStop);
            researchAdapter.SetOnItemClickListener(new SeachResultAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(View v, int position) {
                    selectitem(searchStop.get(position));
                }
            });
            researchRecyclerView.swapAdapter(researchAdapter, true);
        }
    }
}
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import de.greenrobot.event.EventBus;
import flying.grub.tamtime.R;
import flying.grub.tamtime.adapter.HomeAdapter;
import flying.grub.tamtime.data.Data;
import flying.grub.tamtime.data.persistence.FavoriteStopLine;
import flying.grub.tamtime.data.map.Line;
import flying.grub.tamtime.data.real_time.RealTimeToUpdate;
import flying.grub.tamtime.data.update.MessageUpdate;
import flying.grub.tamtime.data.map.StopZone;
import flying.grub.tamtime.data.update.UpdateRunnable;
import flying.grub.tamtime.layout.FavHomeView;
import flying.grub.tamtime.layout.SearchView;
package flying.grub.tamtime.fragment;




public class HomeFragment extends Fragment {

    private static final String TAG = HomeFragment.class.getSimpleName();

    public FavHomeView favHomeView;
    public SearchView searchView;

    private RecyclerView favStopLinesRecycler;
    private HomeAdapter homeAdapter;
    private FavoriteStopLine favoriteStopLine;

    private UpdateRunnable updateRunnable;