<commit_before>/*
 * Copyright © 2012 dvbviewer-controller Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.dvbviewer.controller.ui.fragments;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.PopupMenu;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.espian.showcaseview.ShowcaseView;
import com.espian.showcaseview.targets.ViewTarget;
import com.squareup.picasso.Picasso;

import org.dvbviewer.controller.R;
import org.dvbviewer.controller.data.ProviderConsts;
import org.dvbviewer.controller.data.ProviderConsts.ChannelTbl;
import org.dvbviewer.controller.data.ProviderConsts.EpgTbl;
import org.dvbviewer.controller.entities.Channel;
import org.dvbviewer.controller.entities.DVBViewerPreferences;
import org.dvbviewer.controller.entities.Timer;
import org.dvbviewer.controller.io.ServerRequest.DVBViewerCommand;
import org.dvbviewer.controller.ui.base.BaseListFragment;
import org.dvbviewer.controller.ui.phone.StreamConfigActivity;
import org.dvbviewer.controller.ui.phone.TimerDetailsActivity;
import org.dvbviewer.controller.ui.widget.CheckableLinearLayout;
import org.dvbviewer.controller.utils.AnalyticsTracker;
import org.dvbviewer.controller.utils.DateUtils;
import org.dvbviewer.controller.utils.FileType;
import org.dvbviewer.controller.utils.ServerConsts;
import org.dvbviewer.controller.utils.StreamUtils;
import org.dvbviewer.controller.utils.UIUtils;

import java.text.MessageFormat;
import java.util.Date;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * The Class ChannelList.
 *
 * @author RayBa
 */
public class ChannelList extends BaseListFragment implements LoaderCallbacks<Cursor>, OnClickListener, PopupMenu.OnMenuItemClickListener {

    public static final Uri                         BASE_CONTENT_URI	        = Uri.parse(ProviderConsts.BASE_CONTENT_URI+"/channelselector");
    public static final String                      KEY_CHANNEL_INDEX 	        = ChannelList.class.getName() + "KEY_CHANNEL_INDEX";
    private static final int                        LOADER_CHANNELLIST          = 101;
    private             long                        mGroupId                    = -1;
    private             int                         mGroupIndex                 = -1;
    private             int                         mChannelIndex               = -1;
    private             boolean                     showFavs;
    private             DVBViewerPreferences        prefs;
    private             ChannelAdapter              mAdapter;
    private             OnChannelSelectedListener   mCHannelSelectedListener;
    private             ChannelPagedObserver        mChannelPagedOberserver;

    /*
     * (non-Javadoc)
     *
     * @see android.support.v4.app.Fragment#onCreate(android.os.Bundle)
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        prefs = new DVBViewerPreferences(getContext());
        showFavs = prefs.getPrefs().getBoolean(DVBViewerPreferences.KEY_CHANNELS_USE_FAVS, false);
        mAdapter = new ChannelAdapter(getContext());
        getExtras(savedInstanceState);
        registerObserver();
    }

    private void getExtras(Bundle savedInstanceState) {
        if (savedInstanceState == null) {
            if (getArguments().containsKey(ChannelPager.KEY_GROUP_ID)) {
                mGroupId = getArguments().getLong(ChannelPager.KEY_GROUP_ID);
            }
            if (getArguments().containsKey(ChannelPager.KEY_GROUP_INDEX)) {
                mGroupIndex = getArguments().getInt(ChannelPager.KEY_GROUP_INDEX);
            }
            mChannelIndex = getArguments().getInt(KEY_CHANNEL_INDEX, mChannelIndex);
        }else{
            mGroupId = savedInstanceState.getLong(ChannelPager.KEY_GROUP_ID);
            mGroupIndex = savedInstanceState.getInt(ChannelPager.KEY_GROUP_INDEX);
            mChannelIndex = savedInstanceState.getInt(KEY_CHANNEL_INDEX, mChannelIndex);
        }
    }

    private void registerObserver() {
        final Handler handler = new Handler();
        final Uri contentUri = BASE_CONTENT_URI.buildUpon().appendPath(String.valueOf(mGroupId)).appendQueryParameter("index", String.valueOf(mChannelIndex)).build();
        mChannelPagedOberserver = new ChannelPagedObserver(handler);
        getContext().getContentResolver().registerContentObserver(contentUri, true, mChannelPagedOberserver);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * com.actionbarsherlock.app.SherlockListFragment#onAttach(android.app.Activity
     * )
     */
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnChannelSelectedListener) {
            mCHannelSelectedListener = (OnChannelSelectedListener) context;
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see android.support.v4.app.Fragment#onActivityCreated(android.os.Bundle)
     */
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setListAdapter(mAdapter);
        getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        setEmptyText(showFavs ? getResources().getString(R.string.no_favourites) : getResources().getString(R.string.no_channels));
        Loader<Cursor> loader = getLoaderManager().initLoader(LOADER_CHANNELLIST, savedInstanceState, this);
        setListShown(!(!isResumed() || loader.isStarted()));
        setSelection(mChannelIndex);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader(int,
     * android.os.Bundle)
     */
    @Override
    public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) {
        Loader<Cursor> loader;
        StringBuilder selection = new StringBuilder(ChannelTbl.FLAGS + " & " + Channel.FLAG_ADDITIONAL_AUDIO + "== 0");
        if (mGroupId > 0) {
            selection.append(" and ");
            selection.append(ChannelTbl.GROUP_ID).append(" = ").append(mGroupId);
        }

        loader = new CursorLoader(getContext(), ChannelTbl.CONTENT_URI_NOW, null, selection.toString(), null, ChannelTbl.POSITION);
        return loader;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished(android
     * .support.v4.content.Loader, java.lang.Object)
     */
    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        mAdapter.changeCursor(cursor);
        setSelection(mChannelIndex);
        getListView().setSelectionFromTop(mChannelIndex, (int) getResources().getDimension(R.dimen.list_preferred_item_height_small) * 3);
        setListShown(true);
        getActivity().supportInvalidateOptionsMenu();
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset(android
     * .support.v4.content.Loader)
     */
    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
        arg0.reset();
        if (isVisible()) {
            setListShown(true);
        }
    }




    @Override
    public boolean onMenuItemClick(MenuItem item) {
        Cursor c = mAdapter.getCursor();
        c.moveToPosition(mChannelIndex);
        switch (item.getItemId()) {
            case R.id.menuStreamDirect:
                streamDirect(c);
                return true;
            case R.id.menuStreamTranscoded:
                streamTranscoded(c);
                return true;
            case R.id.menuStreamConfig:
                showStreamConfig(c);
                return true;<commit_msg>fixed possible cursor problems<commit_after>/*
 * Copyright © 2012 dvbviewer-controller Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.dvbviewer.controller.ui.fragments;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.PopupMenu;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.espian.showcaseview.ShowcaseView;
import com.espian.showcaseview.targets.ViewTarget;
import com.squareup.picasso.Picasso;

import org.dvbviewer.controller.R;
import org.dvbviewer.controller.data.ProviderConsts;
import org.dvbviewer.controller.data.ProviderConsts.ChannelTbl;
import org.dvbviewer.controller.data.ProviderConsts.EpgTbl;
import org.dvbviewer.controller.entities.Channel;
import org.dvbviewer.controller.entities.DVBViewerPreferences;
import org.dvbviewer.controller.entities.Timer;
import org.dvbviewer.controller.io.ServerRequest.DVBViewerCommand;
import org.dvbviewer.controller.ui.base.BaseListFragment;
import org.dvbviewer.controller.ui.phone.StreamConfigActivity;
import org.dvbviewer.controller.ui.phone.TimerDetailsActivity;
import org.dvbviewer.controller.ui.widget.CheckableLinearLayout;
import org.dvbviewer.controller.utils.AnalyticsTracker;
import org.dvbviewer.controller.utils.DateUtils;
import org.dvbviewer.controller.utils.FileType;
import org.dvbviewer.controller.utils.ServerConsts;
import org.dvbviewer.controller.utils.StreamUtils;
import org.dvbviewer.controller.utils.UIUtils;

import java.text.MessageFormat;
import java.util.Date;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * The Class ChannelList.
 *
 * @author RayBa
 */
public class ChannelList extends BaseListFragment implements LoaderCallbacks<Cursor>, OnClickListener, PopupMenu.OnMenuItemClickListener {

    public static final Uri                         BASE_CONTENT_URI	        = Uri.parse(ProviderConsts.BASE_CONTENT_URI+"/channelselector");
    public static final String                      KEY_CHANNEL_INDEX 	        = ChannelList.class.getName() + "KEY_CHANNEL_INDEX";
    private static final int                        LOADER_CHANNELLIST          = 101;
    private             long                        mGroupId                    = -1;
    private             int                         mGroupIndex                 = -1;
    private             int                         mChannelIndex               = -1;
    private             boolean                     showFavs;
    private             DVBViewerPreferences        prefs;
    private             ChannelAdapter              mAdapter;
    private             OnChannelSelectedListener   mCHannelSelectedListener;
    private             ChannelPagedObserver        mChannelPagedOberserver;

    /*
     * (non-Javadoc)
     *
     * @see android.support.v4.app.Fragment#onCreate(android.os.Bundle)
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        prefs = new DVBViewerPreferences(getContext());
        showFavs = prefs.getPrefs().getBoolean(DVBViewerPreferences.KEY_CHANNELS_USE_FAVS, false);
        mAdapter = new ChannelAdapter(getContext());
        getExtras(savedInstanceState);
        registerObserver();
    }

    private void getExtras(Bundle savedInstanceState) {
        if (savedInstanceState == null) {
            if (getArguments().containsKey(ChannelPager.KEY_GROUP_ID)) {
                mGroupId = getArguments().getLong(ChannelPager.KEY_GROUP_ID);
            }
            if (getArguments().containsKey(ChannelPager.KEY_GROUP_INDEX)) {
                mGroupIndex = getArguments().getInt(ChannelPager.KEY_GROUP_INDEX);
            }
            mChannelIndex = getArguments().getInt(KEY_CHANNEL_INDEX, mChannelIndex);
        }else{
            mGroupId = savedInstanceState.getLong(ChannelPager.KEY_GROUP_ID);
            mGroupIndex = savedInstanceState.getInt(ChannelPager.KEY_GROUP_INDEX);
            mChannelIndex = savedInstanceState.getInt(KEY_CHANNEL_INDEX, mChannelIndex);
        }
    }

    private void registerObserver() {
        final Handler handler = new Handler();
        final Uri contentUri = BASE_CONTENT_URI.buildUpon().appendPath(String.valueOf(mGroupId)).appendQueryParameter("index", String.valueOf(mChannelIndex)).build();
        mChannelPagedOberserver = new ChannelPagedObserver(handler);
        getContext().getContentResolver().registerContentObserver(contentUri, true, mChannelPagedOberserver);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * com.actionbarsherlock.app.SherlockListFragment#onAttach(android.app.Activity
     * )
     */
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnChannelSelectedListener) {
            mCHannelSelectedListener = (OnChannelSelectedListener) context;
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see android.support.v4.app.Fragment#onActivityCreated(android.os.Bundle)
     */
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setListAdapter(mAdapter);
        getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        setEmptyText(showFavs ? getResources().getString(R.string.no_favourites) : getResources().getString(R.string.no_channels));
        Loader<Cursor> loader = getLoaderManager().initLoader(LOADER_CHANNELLIST, savedInstanceState, this);
        setListShown(!(!isResumed() || loader.isStarted()));
        setSelection(mChannelIndex);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader(int,
     * android.os.Bundle)
     */
    @Override
    public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) {
        Loader<Cursor> loader;
        StringBuilder selection = new StringBuilder(ChannelTbl.FLAGS + " & " + Channel.FLAG_ADDITIONAL_AUDIO + "== 0");
        if (mGroupId > 0) {
            selection.append(" and ");
            selection.append(ChannelTbl.GROUP_ID).append(" = ").append(mGroupId);
        }

        loader = new CursorLoader(getContext(), ChannelTbl.CONTENT_URI_NOW, null, selection.toString(), null, ChannelTbl.POSITION);
        return loader;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.support.v4.app.LoaderManager.LoaderCallbacks#onLoadFinished(android
     * .support.v4.content.Loader, java.lang.Object)
     */
    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        mAdapter.changeCursor(cursor);
        setSelection(mChannelIndex);
        getListView().setSelectionFromTop(mChannelIndex, (int) getResources().getDimension(R.dimen.list_preferred_item_height_small) * 3);
        setListShown(true);
        if(getActivity() != null) {
            getActivity().invalidateOptionsMenu();
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.support.v4.app.LoaderManager.LoaderCallbacks#onLoaderReset(android
     * .support.v4.content.Loader)
     */
    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {

    }




    @Override
    public boolean onMenuItemClick(MenuItem item) {
        Cursor c = mAdapter.getCursor();
        c.moveToPosition(mChannelIndex);
        switch (item.getItemId()) {
            case R.id.menuStreamDirect:
                streamDirect(c);
                return true;
            case R.id.menuStreamTranscoded:
                streamTranscoded(c);
                return true;
            case R.id.menuStreamConfig:
                showStreamConfig(c);
                return true;
{'fraction_non_alphanumeric': 0.095524197993606, 'fraction_numerical': 0.00391357071987653, 'mean_word_length': 3.045261984392419, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '834683', 'n_tokens_mistral': 5151, 'n_tokens_neox': 5000, 'n_words': 900}