com.aptoide.amethyst.AppViewActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.aptoide.amethyst.AppViewActivity.java

Source

/*******************************************************************************
 * Copyright (c) 2015 Aptoide.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 ******************************************************************************/
package com.aptoide.amethyst;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import com.aptoide.amethyst.adapters.SpannableRecyclerAdapter;
import com.aptoide.amethyst.analytics.Analytics;
import com.aptoide.amethyst.configuration.AptoideConfiguration;
import com.aptoide.amethyst.database.AptoideDatabase;
import com.aptoide.amethyst.dialogs.AptoideDialog;
import com.aptoide.amethyst.dialogs.DialogPermissions;
import com.aptoide.amethyst.dialogs.FlagApkDialog;
import com.aptoide.amethyst.dialogs.MyAppStoreDialog;
import com.aptoide.amethyst.downloadmanager.model.Download;
import com.aptoide.amethyst.events.BusProvider;
import com.aptoide.amethyst.events.OttoEvents;
import com.aptoide.amethyst.model.json.CheckUserCredentialsJson;
import com.aptoide.amethyst.models.EnumStoreTheme;
import com.aptoide.amethyst.preferences.Preferences;
import com.aptoide.amethyst.preferences.SecurePreferences;
import com.aptoide.amethyst.ui.IMediaObject;
import com.aptoide.amethyst.ui.MyAccountActivity;
import com.aptoide.amethyst.ui.Screenshot;
import com.aptoide.amethyst.ui.Video;
import com.aptoide.amethyst.ui.callbacks.AddCommentCallback;
import com.aptoide.amethyst.utils.AptoideUtils;
import com.aptoide.amethyst.utils.Logger;
import com.aptoide.amethyst.webservices.AddApkFlagRequest;
import com.aptoide.amethyst.webservices.CheckUserCredentialsRequest;
import com.aptoide.amethyst.webservices.json.GetApkInfoJson;
import com.aptoide.amethyst.webservices.v2.AddApkCommentVoteRequest;
import com.aptoide.amethyst.webservices.v2.AddCommentRequest;
import com.aptoide.amethyst.webservices.v2.AlmostGenericResponseV2RequestListener;
import com.aptoide.amethyst.webservices.v2.GetAdsRequest;
import com.aptoide.dataprovider.AptoideSpiceHttpService;
import com.aptoide.dataprovider.webservices.AllCommentsRequest;
import com.aptoide.dataprovider.webservices.json.GenericResponseV2;
import com.aptoide.dataprovider.webservices.models.Constants;
import com.aptoide.dataprovider.webservices.models.Defaults;
import com.aptoide.dataprovider.webservices.models.GetAppModel;
import com.aptoide.dataprovider.webservices.models.v2.GetComments;
import com.aptoide.dataprovider.webservices.models.v3.RateApp;
import com.aptoide.dataprovider.webservices.models.v7.GetApp;
import com.aptoide.dataprovider.webservices.models.v7.GetAppMeta;
import com.aptoide.models.ApkSuggestionJson;
import com.aptoide.models.displayables.Displayable;
import com.aptoide.models.displayables.HeaderRow;
import com.aptoide.models.displayables.MoreVersionsAppViewItem;
import com.aptoide.models.displayables.NoCommentPlaceHolderRow;
import com.aptoide.models.stores.Store;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import com.crashlytics.android.Crashlytics;
import com.flurry.android.FlurryAgent;
import com.octo.android.robospice.SpiceManager;
import com.octo.android.robospice.exception.NoNetworkException;
import com.octo.android.robospice.persistence.DurationInMillis;
import com.octo.android.robospice.persistence.exception.SpiceException;
import com.octo.android.robospice.request.listener.RequestListener;
import com.octo.android.robospice.retry.RetryPolicy;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.squareup.otto.Subscribe;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IllegalFormatException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.aptoide.amethyst.adapter.DividerItemDecoration;
import com.aptoide.amethyst.adapter.ScreenshotsAdapter;
import com.aptoide.amethyst.adapter.store.CommentsStoreAdapter;
import com.aptoide.amethyst.callbacks.AddCommentVoteCallback;
import com.aptoide.amethyst.fragments.store.LatestCommentsFragment;
import com.aptoide.amethyst.openiab.PaidAppPurchaseActivity;
import com.aptoide.amethyst.services.DownloadService;
import com.aptoide.amethyst.ui.MoreCommentsActivity;
import com.aptoide.amethyst.ui.MoreVersionsActivity;
import com.aptoide.amethyst.ui.SearchManager;
import com.aptoide.amethyst.ui.WrappingLinearLayoutManager;
import com.aptoide.amethyst.ui.widget.CircleTransform;
import com.aptoide.amethyst.utils.ReferrerUtils;
import com.aptoide.amethyst.webservices.GetApkInfoRequestFromId;

import lombok.Getter;

import static com.aptoide.dataprovider.webservices.models.v7.GetAppMeta.File.Malware.TRUSTED;
import static com.aptoide.dataprovider.webservices.models.v7.GetAppMeta.File.Malware.UNKNOWN;
import static com.aptoide.dataprovider.webservices.models.v7.GetAppMeta.File.Malware.WARNING;

/**
 *
 * Created by hsousa
 */
public class AppViewActivity extends AptoideBaseActivity
        implements AddCommentVoteCallback, FlagApkDialog.ApkFlagCallback {

    /**
     * True when activity is created.
     */
    private boolean lifecycleController = false;
    static String TAG = AppViewActivity.class.getSimpleName();
    public static final short DOWNGRADE_REQUEST_CODE = 456;
    private static final short Purchase_REQUEST_CODE = 30333;
    private static final short MAX_VISIBLE_COMMENTS = 3;

    private static final short MAX_COMMENTS_REQUEST = 4;

    private static final String APP_NOT_AVAILABLE = "410 Gone";

    private ResultBundle resultBundle;

    private static int getPercentage(Number total, Number quantity) {
        if (quantity.intValue() == 0 || total.intValue() == 0) {
            return 0;
        } else {
            return (quantity.intValue() * 100 / total.intValue());
        }
    }

    @Nullable
    private static PackageInfo getPackageInfo(Context context, String packageName) {
        try {
            return context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
        } catch (PackageManager.NameNotFoundException e) {
            return null;
        }
    }

    static class ResultBundle {
        final int requestCode;
        final int resultCode;
        final Intent data;

        public ResultBundle(int requestCode, int resultCode, Intent data) {
            this.requestCode = requestCode;
            this.resultCode = resultCode;
            this.data = data;
        }
    }

    enum BtnInstallState {
        INSTALL(0), DOWNGRADE(1), UPDATE(2), OPEN(3), BUY(4);
        int state;

        BtnInstallState(int state) {
            this.state = state;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.app_view_activity);
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.content, AppViewFragment.newInstance(lifecycleController)).commit();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.content);
        if (fragment != null && resultBundle != null) {
            fragment.onActivityResult(resultBundle.requestCode, resultBundle.resultCode, resultBundle.data);
            resultBundle = null;
        }

        lifecycleController = true;
    }

    @Override
    protected void onStop() {
        final FragmentManager manager = getSupportFragmentManager();
        final Fragment fragment = manager.findFragmentById(R.id.content);
        manager.beginTransaction().remove(fragment).commitAllowingStateLoss();
        super.onStop();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        final AppViewFragment fragment = AppViewFragment.newInstance(lifecycleController);
        final FragmentManager manager = getSupportFragmentManager();
        manager.beginTransaction().replace(R.id.content, fragment).commitAllowingStateLoss();
    }

    @Override
    protected String getScreenName() {
        return "App View";
    }

    @Override
    public void voteComment(final int commentId, final AddApkCommentVoteRequest.CommentVote vote) {
        final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.content);
        if (fragment != null) {
            ((AddCommentVoteCallback) fragment).voteComment(commentId, vote);
        }
    }

    @Override
    public void addApkFlagClick(final String flag) {
        final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.content);
        if (fragment != null) {
            ((FlagApkDialog.ApkFlagCallback) fragment).addApkFlagClick(flag);
        }
    }

    @Nullable
    public DownloadService getService() {
        final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.content);
        if (fragment != null) {
            return ((AppViewFragment) fragment).downloadService;
        }
        return null;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        resultBundle = new ResultBundle(requestCode, resultCode, data);
    }

    public static class AppViewFragment extends Fragment
            implements FlagApkDialog.ApkFlagCallback, AddCommentVoteCallback, ServiceConnection {

        private String download_from;

        private static final String BADGE_DIALOG_TAG = "badgeDialog";
        protected SpiceManager spiceManager = new SpiceManager(AptoideSpiceHttpService.class);
        private boolean lifecycleController;

        public static AppViewFragment newInstance(boolean lifecycleController) {
            AppViewFragment f = new AppViewFragment();
            Bundle args = new Bundle();
            args.putBoolean("lifecycleController", lifecycleController);
            f.setArguments(args);
            return f;
        }

        public AppViewFragment() {
        }

        Toolbar mToolbar;
        ImageView mFeaturedGraphic;
        ImageView mAppIcon;
        View mStoreView;
        ImageView mStoreAvatar;
        TextView mStoreName;
        TextView mStoreUsers;
        CollapsingToolbarLayout mCollapsingToolbarLayout;
        TextView mVersionName;
        TextView mDownloadsNumber;
        TextView mFileSize;
        RatingBar mRatingBarTop;
        RatingBar mRatingBar;
        TextView mDescription;
        TextView mSeeMore;
        LinearLayout mSeeMoreLayout;

        Button mButtonInstall;
        NestedScrollView mContentView;
        ProgressBar mProgressBar;
        AppBarLayout mAppBarLayout;
        ScrollView layoutNoNetwork;
        ScrollView layoutError;
        ScrollView layoutError410;
        TextView retryError;
        TextView retryNoNetwork;
        RecyclerView recyclerComments;
        TextView mSeeMoreComments;
        LinearLayout mLatestVersionLayout;
        Button mButtonGetLatest;
        Button mButtonUninstall;
        Button mButtonSubscribe;
        RelativeLayout mTrustedLayout;
        RelativeLayout mWarningLayout;
        RelativeLayout mUnknownLayoutt;
        RelativeLayout badgeLayout;
        ImageView mBadgeMarket;
        ImageView mBadgeSignature;
        ImageView mBadgeFlag;
        ImageView mBadgeAntiVirus;
        LinearLayout mFlagsLayout;
        Button mButtonFlagThisApp;
        ImageView mArrow;
        TextView tvAgvRating;
        TextView tvNumberRates;
        ProgressBar progressBarRating5;
        ProgressBar progressBarRating4;
        ProgressBar progressBarRating3;
        ProgressBar progressBarRating2;
        ProgressBar progressBarRating1;
        RatingBar avgRatingBar;
        TextView tvNumberOfStarts5;
        TextView tvNumberOfStarts4;
        TextView tvNumberOfStarts3;
        TextView tvNumberOfStarts2;
        TextView tvNumberOfStarts1;
        TextView tvNumberGoodFlags;
        TextView tvNumberFakeFlags;
        TextView tvNumberFreezeFlags;
        TextView tvNumberLicenceFlags;
        TextView tvNumberVirusFlags;
        View manualReviewLayout;
        LinearLayout mInstallAndLatestVersionLayout;
        RelativeLayout mDownloadProgressLayout;
        ImageView mActionResume;
        TextView mProgressText;
        ProgressBar mDownloadingProgress;
        RelativeLayout mMoreVersionsLayoutHeader;
        Button mMoreVersionsLayoutButton;
        TextView mMoreVersionsTitle;
        TextView mWebsiteLabel;
        TextView mEmailLabel;
        TextView mPrivacyLabel;
        TextView mPermissionsLabel;
        RecyclerView mScreenshotsList;

        RecyclerView mMoreVersionsList;

        int descriptionLines;

        private String cpd;
        private String[] referrer = new String[1];
        private WebView[] webview = new WebView[1];

        private boolean fromSponsored;

        private DownloadService downloadService;
        private volatile CountDownLatch downloadServiceLatch;
        ////// evil fields from the v6's AppView
        private boolean isPaidToschedule = true;
        private String installedSignature;
        private boolean isFromActivityResult;
        private boolean autoDownload;
        private boolean isDownloadCompleted;

        private int bucketSize;
        private int recyclerOffset;

        /** See More/Less description logic */
        private boolean extended = false;

        /** Y coordinate in order to scroll when hiding the description */
        int scrollPosition = 0;

        /**
         * v7 json attributes
         */
        @Getter
        private long appId;
        private long adId;
        private String signature;
        private String path;
        private long fileSize; //this is just the fileSize of the apk
        private String altPath;
        private String appName;
        private String versionName;
        private int versionCode;
        private long downloads;
        private String packageName;
        private String developer;
        private String storeName;
        private String storeAvatar;
        private EnumStoreTheme storeTheme;
        private long storeSubscribers;
        private String screen;
        private int minSdk;
        private GetAppMeta.Pay pay;
        private String md5sum;
        private String iconUrl;
        private float rating;
        private long storeId;
        private String description;
        private String graphic;
        private String wUrl;
        private String userVote;
        private GetAppMeta.Obb obb;
        private List<String> permissions;
        private GetAppMeta.File.Malware malware;
        private String website;
        private String email;

        private String privacy;

        /**
         * In v6 is the hashCode of the md5sum. Used as an Id for the downloadService
         */
        private long downloadId;
        private List<GetAppMeta.Media.Screenshot> screenshots;
        private List<GetAppMeta.Media.Video> videos;
        /**
         * Atributes for comments
         */
        protected List<Displayable> displayableCommentsList = new ArrayList<>();
        /**
         * flag to control when the secondary requests should use cache or not
         */
        boolean forceReload;
        /**
         * Flag to inform if there is a more recent version
         */
        boolean latestAvailable;
        /**
         * When it's not the latest, use this Id to call a new AppViewActivity
         */
        long latestAppId;
        /**
         * Flag to inform if the app is an update to an already installed app
         */
        boolean isUpdate;
        /**
         * Controls if the App is installed
         */
        boolean isInstalled;
        /**
         * Used to control the cache of GetApkInfo, for the "pay app" use-case
         */
        private boolean refreshOnResume;
        /**
         * When we want an app to start autoDownloading <b>without</b> showing the yes/no dialog
         * (but can still show the "Root" dialog)
         */
        boolean forceAutoDownload;

        private ApkSuggestionJson.Ads appSuggested;

        private RequestManager glide;

        /**
         * Used to control when we need to refresh the install/open button when coming back from the onResume
         */
        private boolean reloadButtons;

        private ResultBundle resultBundle;

        private RequestListener<GetAppModel> listener = new RequestListener<GetAppModel>() {

            @Override
            public void onRequestFailure(SpiceException spiceException) {
                handleErrorCondition(spiceException);
            }

            @Override
            public void onRequestSuccess(GetAppModel model) {
                boolean unrecoverableErrorsFound = false;
                try {
                    appId = model.getApp.nodes.meta.data.id.longValue();
                    signature = model.getApp.nodes.meta.data.file.signature.sha1;
                    path = model.getApp.nodes.meta.data.file.path;
                    altPath = model.getApp.nodes.meta.data.file.pathAlt;
                    fileSize = model.getApp.nodes.meta.data.file.filesize.longValue();
                    appName = model.getApp.nodes.meta.data.name;
                    versionName = model.getApp.nodes.meta.data.file.vername;
                    versionCode = model.getApp.nodes.meta.data.file.vercode.intValue();
                    downloads = model.getApp.nodes.meta.data.stats.downloads.longValue();
                    packageName = model.getApp.nodes.meta.data.packageName;
                    developer = model.getApp.nodes.meta.data.developer.name;
                    website = model.getApp.nodes.meta.data.developer.website;
                    email = model.getApp.nodes.meta.data.developer.email;
                    privacy = model.getApp.nodes.meta.data.developer.privacy;
                    storeName = model.getApp.nodes.meta.data.store.name;
                    storeAvatar = model.getApp.nodes.meta.data.store.avatar;
                    storeSubscribers = model.getApp.nodes.meta.data.store.stats.subscribers.longValue();
                    storeTheme = EnumStoreTheme.get(model.getApp.nodes.meta.data.store.appearance.theme);
                    screen = model.getApp.nodes.meta.data.file.hardware.screen;
                    minSdk = model.getApp.nodes.meta.data.file.hardware.sdk.intValue();
                    pay = model.getApp.nodes.meta.data.pay;
                    md5sum = model.getApp.nodes.meta.data.file.md5sum;
                    iconUrl = AptoideUtils.UI.parseIcon(getActivity(), model.getApp.nodes.meta.data.icon);
                    rating = model.getApp.nodes.meta.data.stats.rating.avg.floatValue();
                    screenshots = model.getApp.nodes.meta.data.media.screenshots;
                    videos = model.getApp.nodes.meta.data.media.videos;
                    graphic = model.getApp.nodes.meta.data.graphic;
                    wUrl = model.getApp.nodes.meta.data.urls.w;
                    storeId = model.getApp.nodes.meta.data.store.id.longValue();
                    description = model.getApp.nodes.meta.data.media.description;
                    downloadId = md5sum.hashCode();
                    obb = model.getApp.nodes.meta.data.obb;
                    permissions = model.getApp.nodes.meta.data.file.usedPermissions;
                    malware = model.getApp.nodes.meta.data.file.malware;

                    Analytics.ViewedApplication.view(packageName, developer, download_from);

                    if (model.getApp.nodes.versions != null && !model.getApp.nodes.versions.list.isEmpty()
                            && model.getApp.nodes.meta.data.file.vercode
                                    .longValue() < model.getApp.nodes.versions.list.get(0).file.vercode
                                            .longValue()) {

                        latestAvailable = true;
                        latestAppId = model.getApp.nodes.versions.list.get(0).id.longValue();
                    }

                } catch (Exception e) {
                    Crashlytics.logException(e);
                    Crashlytics.setLong("appId", appId);
                    Crashlytics.setString("packageName", packageName);
                    Crashlytics.setString("md5sum", md5sum);
                    handleErrorCondition(e);
                    unrecoverableErrorsFound = true;
                }

                if (!unrecoverableErrorsFound) {
                    handleSuccessCondition();
                    updateUI();
                    updateBadges();
                    updateFlags(model.getApp);
                    populateScreenShotsView();
                    populateSeeMore();
                    populatePermissionsTable(model.getApp);
                    updateStoreInfo();
                    checkInstallation();
                    handleLatestVersionLogic();
                    populateMoreVersions(model);
                    requestComments(false);
                    showDialogIfComingFromBrowser();
                    showDialogIfComingFromAPKFY();
                    populateRatings(model.getApp);

                    if (!fromSponsored) {
                        new AppViewMiddleSuggested((AppViewActivity) getActivity(),
                                getView().findViewById(R.id.middleAppViewContainer), spiceManager, appId,
                                packageName, model.getApp.nodes.meta.data.media.keywords);
                        getOrganicAds();
                    }

                    if (isFromActivityResult || forceAutoDownload) {
                        download();
                    }

                    if (resultBundle != null) {
                        onActivityResult(resultBundle.requestCode, resultBundle.resultCode, resultBundle.data);
                        resultBundle = null;
                    }
                }
            }
        };

        private boolean isApkFy;
        private static boolean isApkFyDialogShowed = false;

        private void showDialogIfComingFromAPKFY() {
            if (obb != null) {
                AptoideUtils.AppUtils.checkPermissions(getActivity());
            }

            isApkFy = getActivity().getIntent().getBooleanExtra(Constants.FROM_APKFY_KEY, false);
            if (isApkFy && !isPaidApp() && !isApkFyDialogShowed) {
                isApkFyDialogShowed = true;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    SharedPreferences.Editor edit = PreferenceManager
                            .getDefaultSharedPreferences(Aptoide.getContext()).edit();
                    edit.putString(AptoideConfiguration.PREF_PATH_CACHE_APK,
                            Aptoide.getContext().getFilesDir().getPath()).apply();
                }
                final InstallListener installListener = new InstallListener(iconUrl, appName, versionName,
                        packageName, md5sum, isPaidApp());
                DialogFragment dialog = AptoideDialog.myAppInstall(appName, installListener, null);
                AptoideDialog.showDialogAllowingStateLoss(dialog, getChildFragmentManager(),
                        Constants.FROM_APKFY_KEY);
            }
        }

        private RequestListener<GetApkInfoJson> getApkInfoJsonRequestListener = new RequestListener<GetApkInfoJson>() {

            @Override
            public void onRequestFailure(SpiceException spiceException) {
            }

            @Override
            public void onRequestSuccess(GetApkInfoJson getApkInfoJson) {
                final GetApkInfoJson.Payment payment = getApkInfoJson.getPayment();

                Logger.d("AppViewActivity", "User_ID: " + SecurePreferences.getInstance().getInt("User_ID", 0));
                getActivity().supportInvalidateOptionsMenu();

                if (!getApkInfoJson.getStatus().equals("OK")) {
                    return;
                }

                if (getApkInfoJson.getPayment().status.equals("OK")) {
                    mButtonInstall.setText(R.string.install);
                    InstallListener installListener = new InstallListener(iconUrl, appName, versionName,
                            packageName, md5sum, true);
                    mButtonInstall.setOnClickListener(installListener);
                    mButtonInstall.setVisibility(View.VISIBLE);
                    path = getApkInfoJson.getApk().getPath();
                } else {
                    mButtonInstall.setText(
                            getString(R.string.buy) + " (" + payment.symbol + " " + payment.getAmount() + ")");
                    mButtonInstall.setVisibility(View.VISIBLE);
                    final Activity thisActivity = getActivity();
                    if (SecurePreferences.getInstance().getInt("User_ID", 0) == 0) {
                        Logger.d("AppViewActivity", "is 0, making request");
                        CheckUserCredentialsRequest request = CheckUserCredentialsRequest.buildDefaultRequest(
                                thisActivity, SecurePreferences.getInstance().getString("access_token", null));
                        spiceManager.execute(request, new RequestListener<CheckUserCredentialsJson>() {

                            @Override
                            public void onRequestFailure(SpiceException spiceException) {
                                Toast.makeText(Aptoide.getContext(), R.string.error_occured, Toast.LENGTH_SHORT)
                                        .show();
                            }

                            @Override
                            public void onRequestSuccess(CheckUserCredentialsJson checkUserCredentialsJson) {
                                if ("OK".equals(checkUserCredentialsJson.getStatus())) {
                                    SharedPreferences.Editor securePreferences = SecurePreferences.getInstance()
                                            .edit();

                                    securePreferences.putInt("User_ID", checkUserCredentialsJson.getId());
                                    Logger.d("AppViewActivity",
                                            "updating user id to " + checkUserCredentialsJson.getId());
                                    securePreferences.commit();
                                } else {
                                    Toast.makeText(Aptoide.getContext(), R.string.error_occured, Toast.LENGTH_SHORT)
                                            .show();
                                }
                            }
                        });
                    }

                    mButtonInstall.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            FlurryAgent.logEvent("App_View_Clicked_On_Buy_Button");
                            final AccountManager accountManager = AccountManager.get(thisActivity);
                            final Account[] accounts = accountManager
                                    .getAccountsByType(Aptoide.getConfiguration().getAccountType());

                            if (accounts.length > 0) {
                                final Intent i = new Intent(thisActivity, PaidAppPurchaseActivity.class);
                                i.putExtra("packageName", packageName);
                                i.putExtra("ID", payment.metadata.id);
                                i.putExtra("user", accounts[0].name);
                                i.putExtra("icon", iconUrl);
                                i.putExtra("label", appName);
                                i.putExtra("price", payment.amount.floatValue());
                                i.putExtra("currency_symbol", payment.symbol);
                                i.putParcelableArrayListExtra("PaymentServices",
                                        new ArrayList<Parcelable>(payment.payment_services));

                                startActivityForResult(i, Purchase_REQUEST_CODE);

                            } else {
                                Toast.makeText(Aptoide.getContext(), "You need to login to purchase.",
                                        Toast.LENGTH_LONG).show();
                                accountManager.addAccount(Aptoide.getConfiguration().getAccountType(),
                                        AptoideConfiguration.AccountGeneral.AUTHTOKEN_TYPE_FULL_ACCESS, null, null,
                                        thisActivity, new AccountManagerCallback<Bundle>() {
                                            @Override
                                            public void run(
                                                    AccountManagerFuture<Bundle> bundleAccountManagerFuture) {
                                                refreshOnResume = true;
                                            }
                                        }, new Handler(Looper.getMainLooper()));
                            }
                        }
                    });
                }
                mButtonInstall.setVisibility(View.VISIBLE);
            }
        };

        @Override
        public void onCreate(@Nullable final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setHasOptionsMenu(true);
            glide = Glide.with(this);

            lifecycleController = getArguments().getBoolean("lifecycleController");

            if (savedInstanceState != null) {
                appId = savedInstanceState.getLong(Constants.APP_ID_KEY);
                appName = savedInstanceState.getString(Constants.APPNAME_KEY);
                fileSize = savedInstanceState.getLong(Constants.FILESIZE_KEY);
                downloadId = savedInstanceState.getLong(Constants.DOWNLOAD_ID_KEY);
                downloads = savedInstanceState.getLong(Constants.DOWNLOADS_KEY);
                storeId = savedInstanceState.getLong(Constants.STOREID_KEY);
                storeAvatar = savedInstanceState.getString(Constants.STOREAVATAR_KEY);
                packageName = savedInstanceState.getString(Constants.PACKAGENAME_KEY);
                versionName = savedInstanceState.getString(Constants.VERSIONNAME_KEY);
                md5sum = savedInstanceState.getString(Constants.MD5SUM_KEY);
            } else {
                forceAutoDownload = getActivity().getIntent().getBooleanExtra("forceAutoDownload", false);
            }
        }

        @Nullable
        @Override
        public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
                @Nullable final Bundle savedInstanceState) {
            BusProvider.getInstance().register(this);
            spiceManager.start(getActivity());
            final View view = inflater.inflate(R.layout.fragment_app_view, container, false);
            bindViews(view);
            recyclerOffset = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4,
                    getResources().getDisplayMetrics());
            bucketSize = AptoideUtils.UI.getBucketSize();
            mRatingBar.setOnRatingBarChangeListener(new RatingBarClickListener());
            return view;
        }

        private void bindViews(View view) {
            mToolbar = (Toolbar) view.findViewById(R.id.toolbar);
            mFeaturedGraphic = (ImageView) view.findViewById(R.id.featured_graphic);
            mAppIcon = (ImageView) view.findViewById(R.id.app_icon);
            mStoreView = (View) view.findViewById(R.id.store);
            mStoreAvatar = (ImageView) view.findViewById(R.id.store_avatar);
            mStoreName = (TextView) view.findViewById(R.id.store_name);
            mStoreUsers = (TextView) view.findViewById(R.id.store_number_users);
            mCollapsingToolbarLayout = (CollapsingToolbarLayout) view.findViewById(R.id.collapsing_toolbar);
            mVersionName = (TextView) view.findViewById(R.id.versionName);
            mDownloadsNumber = (TextView) view.findViewById(R.id.downloads_number);
            mFileSize = (TextView) view.findViewById(R.id.file_size);
            mRatingBarTop = (RatingBar) view.findViewById(R.id.rating_bar_top);
            mRatingBar = (RatingBar) view.findViewById(R.id.ratingbar_appview);
            mDescription = (TextView) view.findViewById(R.id.description);
            mSeeMore = (TextView) view.findViewById(R.id.see_more_button);
            mSeeMoreLayout = (LinearLayout) view.findViewById(R.id.see_more_layout);
            mButtonInstall = (Button) view.findViewById(R.id.btn_install);
            mContentView = (NestedScrollView) view.findViewById(R.id.scrollview_content);
            mProgressBar = (ProgressBar) view.findViewById(R.id.progress);
            mAppBarLayout = (AppBarLayout) view.findViewById(R.id.appbar);
            layoutNoNetwork = (ScrollView) view.findViewById(R.id.no_network_connection);
            layoutError = (ScrollView) view.findViewById(R.id.error);
            layoutError410 = (ScrollView) view.findViewById(R.id.error410);
            retryError = (TextView) view.findViewById(R.id.retry_error);
            retryNoNetwork = (TextView) view.findViewById(R.id.retry_no_network);
            recyclerComments = (RecyclerView) view.findViewById(R.id.appview_comments_list);
            mSeeMoreComments = (TextView) view.findViewById(R.id.see_more_comments);
            mLatestVersionLayout = (LinearLayout) view.findViewById(R.id.latestversion_layout);
            mButtonGetLatest = (Button) view.findViewById(R.id.btn_get_latest);
            mButtonUninstall = (Button) view.findViewById(R.id.btn_uninstall);
            mButtonSubscribe = (Button) view.findViewById(R.id.btn_subscribe);
            mTrustedLayout = (RelativeLayout) view.findViewById(R.id.trusted_layout);
            mWarningLayout = (RelativeLayout) view.findViewById(R.id.warning_layout);
            mUnknownLayoutt = (RelativeLayout) view.findViewById(R.id.unknown_layout);
            badgeLayout = (RelativeLayout) view.findViewById(R.id.badge_layout);
            mBadgeMarket = (ImageView) view.findViewById(R.id.iv_market_badge);
            mBadgeSignature = (ImageView) view.findViewById(R.id.iv_signature_badge);
            mBadgeFlag = (ImageView) view.findViewById(R.id.iv_flag_badge);
            mBadgeAntiVirus = (ImageView) view.findViewById(R.id.iv_antivirus_badge);
            mFlagsLayout = (LinearLayout) view.findViewById(R.id.flags_layout);
            mButtonFlagThisApp = (Button) view.findViewById(R.id.btn_flag_this_app);
            mArrow = (ImageView) view.findViewById(R.id.iv_arrow);
            tvAgvRating = (TextView) view.findViewById(R.id.appview_avg_rating);
            tvNumberRates = (TextView) view.findViewById(R.id.tv_number_of_rates);
            progressBarRating5 = (ProgressBar) view.findViewById(R.id.appview_rating_bar5);
            progressBarRating4 = (ProgressBar) view.findViewById(R.id.appview_rating_bar4);
            progressBarRating3 = (ProgressBar) view.findViewById(R.id.appview_rating_bar3);
            progressBarRating2 = (ProgressBar) view.findViewById(R.id.appview_rating_bar2);
            progressBarRating1 = (ProgressBar) view.findViewById(R.id.appview_rating_bar1);
            avgRatingBar = (RatingBar) view.findViewById(R.id.appview_rating_bar_avg);
            tvNumberOfStarts5 = (TextView) view.findViewById(R.id.appview_rating_bar_rating_number5);
            tvNumberOfStarts4 = (TextView) view.findViewById(R.id.appview_rating_bar_rating_number4);
            tvNumberOfStarts3 = (TextView) view.findViewById(R.id.appview_rating_bar_rating_number3);
            tvNumberOfStarts2 = (TextView) view.findViewById(R.id.appview_rating_bar_rating_number2);
            tvNumberOfStarts1 = (TextView) view.findViewById(R.id.appview_rating_bar_rating_number1);
            tvNumberGoodFlags = (TextView) view.findViewById(R.id.number_good_flags);
            tvNumberFakeFlags = (TextView) view.findViewById(R.id.number_fake_flags);
            tvNumberFreezeFlags = (TextView) view.findViewById(R.id.number_freeze_flags);
            tvNumberLicenceFlags = (TextView) view.findViewById(R.id.number_licence_flags);
            tvNumberVirusFlags = (TextView) view.findViewById(R.id.number_virus_flags);
            manualReviewLayout = (View) view.findViewById(R.id.manual_reviewed_message_layout);
            mInstallAndLatestVersionLayout = (LinearLayout) view
                    .findViewById(R.id.install_and_latest_version_layout);
            mDownloadProgressLayout = (RelativeLayout) view.findViewById(R.id.download_progress_layout);
            mActionResume = (ImageView) view.findViewById(R.id.ic_action_resume);
            mProgressText = (TextView) view.findViewById(R.id.text_progress);
            mDownloadingProgress = (ProgressBar) view.findViewById(R.id.downloading_progress);
            mMoreVersionsLayoutHeader = (RelativeLayout) view.findViewById(R.id.more_layout);
            mMoreVersionsLayoutButton = (Button) view.findViewById(R.id.more);
            mMoreVersionsTitle = (TextView) view.findViewById(R.id.title);
            mWebsiteLabel = (TextView) view.findViewById(R.id.website_label);
            mEmailLabel = (TextView) view.findViewById(R.id.email_label);
            mPrivacyLabel = (TextView) view.findViewById(R.id.privacy_policy_label);
            mPermissionsLabel = (TextView) view.findViewById(R.id.permissions_label);
            mScreenshotsList = (RecyclerView) view.findViewById(R.id.screenshots_list);
            mMoreVersionsList = (RecyclerView) view.findViewById(R.id.more_versions_recycler);

            descriptionLines = view.getContext().getResources().getInteger(R.integer.minimum_description_lines);
        }

        @Override
        public void onViewCreated(final View view, @Nullable final Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            final AppViewActivity appViewActivity = (AppViewActivity) getActivity();
            appViewActivity.setSupportActionBar(mToolbar);
            ActionBar supportActionBar = appViewActivity.getSupportActionBar();
            if (supportActionBar != null) {
                supportActionBar.setDisplayHomeAsUpEnabled(true);
            }
            continueLoading();
        }

        @Override
        public void onStart() {
            super.onStart();
            downloadServiceLatch = new CountDownLatch(1);
            getActivity().bindService(new Intent(getActivity(), DownloadService.class), this, BIND_AUTO_CREATE);
        }

        @Override
        public void onResume() {
            super.onResume();
            if (pay != null && pay.price != null) {
                setupInstallButton();
            }

            if (reloadButtons) {
                checkInstallation();
                updateStoreInfo();
                handleLatestVersionLogic();
                reloadButtons = false;
            }

            populateDownloadUI();
        }

        @Override
        public void onStop() {
            if (downloadService != null) {
                //                downloadService = null;
                getActivity().unbindService(this);
            }
            super.onStop();
        }

        @Override
        public void onDestroyView() {
            BusProvider.getInstance().unregister(this);
            spiceManager.shouldStop();
            if (webview[0] != null) {
                webview[0].removeAllViews();
                webview[0].destroy();
            }
            AptoideUtils.UI.unbindDrawables(getView());
            super.onDestroyView();
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            //            Aptoide.getRefWatcher(getContext()).watch(this);
        }

        @Override
        public void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putLong(Constants.APP_ID_KEY, appId);
            outState.putString(Constants.MD5SUM_KEY, md5sum);
            outState.putString(Constants.APPNAME_KEY, appName);
            outState.putString(Constants.ICON_KEY, iconUrl);
            outState.putLong(Constants.DOWNLOADS_KEY, downloads);
            outState.putFloat(Constants.RATING_KEY, rating);
            outState.putString(Constants.GRAPHIC_KEY, graphic);
            outState.putLong(Constants.FILESIZE_KEY, fileSize);
            outState.putLong(Constants.STOREID_KEY, storeId);
            outState.putString(Constants.STORENAME_KEY, storeName);
            outState.putString(Constants.PACKAGENAME_KEY, packageName);
            outState.putString(Constants.VERSIONNAME_KEY, versionName);
            outState.putLong(Constants.DOWNLOAD_ID_KEY, downloadId);
        }

        @Override
        public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
            super.onCreateOptionsMenu(menu, inflater);
            inflater.inflate(R.menu.menu_appview_activity, menu);
            SearchManager.setupSearch(menu, getActivity());
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            int i = item.getItemId();
            if (i == android.R.id.home) {
                getActivity().onBackPressed();
                return true;
            } else if (i == R.id.menu_share) {
                FlurryAgent.logEvent("App_View_Clicked_On_Share_Button");

                Intent sharingIntent = new Intent(Intent.ACTION_SEND);
                sharingIntent.setType("text/plain");
                sharingIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.install) + " \"" + appName + "\"");
                sharingIntent.putExtra(Intent.EXTRA_TEXT, wUrl);

                if (wUrl != null) {
                    startActivity(Intent.createChooser(sharingIntent, getString(R.string.share)));
                }
            } else if (i == R.id.menu_schedule) {
                new AptoideDatabase(Aptoide.getDb()).scheduledDownloadIfMd5(packageName, md5sum, versionName,
                        storeName, appName, iconUrl);
            }

            return super.onOptionsItemSelected(item);
        }

        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == DOWNGRADE_REQUEST_CODE) {
                try {
                    // md5sum is not loaded yet
                    if (md5sum == null) {
                        resultBundle = new ResultBundle(requestCode, resultCode, data);
                        return;
                    }
                    getActivity().getPackageManager().getPackageInfo(packageName, 0);
                    Toast.makeText(getActivity(), getString(R.string.downgrade_requires_uninstall),
                            Toast.LENGTH_SHORT).show();
                } catch (PackageManager.NameNotFoundException e) {
                    isFromActivityResult = true;
                    executeSpiceRequestWithMd5(md5sum, storeName);
                }
            } else if (requestCode == Purchase_REQUEST_CODE) {
                Logger.d("AppViewActivity", "AppViewActivity onActivityResult Purchase_REQUEST_CODE");
                if (resultCode == RESULT_OK) {
                    refreshOnResume = true;
                    autoDownload = false;
                }
            }
        }

        @Override
        public void onServiceConnected(final ComponentName name, final IBinder service) {
            downloadService = ((DownloadService.LocalBinder) service).getService();

            if (downloadService.getDownload(downloadId).getDownload() != null) {
                onDownloadUpdate(downloadService.getDownload(downloadId).getDownload());
            } else {
                mInstallAndLatestVersionLayout.setVisibility(View.VISIBLE);
                mDownloadProgressLayout.setVisibility(View.GONE);
            }
            downloadServiceLatch.countDown();
        }

        @Override
        public void onServiceDisconnected(final ComponentName name) {
        }

        private void populateSeeMore() {
            if (description != null && description.length() > 250) {
                try {
                    // Fix for AN-348: replace the & with &amp; (that's was causing the pushback buffer full)
                    mDescription.setText(Html.fromHtml(description.replace("\n", "<br/>").replace("&", "&amp;")));
                    mDescription.setMovementMethod(LinkMovementMethod.getInstance());
                    mSeeMoreLayout.setOnClickListener(extendListener);
                } catch (Exception e) {
                    Logger.printException(e);
                    mSeeMoreLayout.setVisibility(View.GONE);
                    mDescription.setText(getString(R.string.error_APK_Description));
                }

            } else {
                mSeeMoreLayout.setVisibility(View.GONE);
                mDescription.setText(getString(R.string.error_APK_Description));
            }
        }

        private void populateRatings(GetApp getApp) {
            if (getApp.nodes == null || getApp.nodes.meta == null || getApp.nodes.meta.data == null
                    || getApp.nodes.meta.data.stats == null || getApp.nodes.meta.data.stats.rating == null) {
                return;
            }

            GetAppMeta.Stats.Rating ratings = getApp.nodes.meta.data.stats.rating;

            try {
                float numberfloat = ratings.avg.floatValue();
                //Avg ratings
                tvAgvRating.setText(String.format("%.1f", numberfloat));
            } catch (NullPointerException | IllegalFormatException e) {
                tvAgvRating.setText(ratings.avg.toString());
            }

            long numberVotes = ratings.votes.get(0).count.longValue() + ratings.votes.get(1).count.longValue()
                    + ratings.votes.get(2).count.longValue() + ratings.votes.get(3).count.longValue()
                    + ratings.votes.get(4).count.longValue();
            tvNumberRates.setText(String.valueOf(numberVotes));
            avgRatingBar.setRating(ratings.avg.floatValue());

            //rating bars
            progressBarRating5.setProgress(getPercentage(numberVotes, ratings.votes.get(0).count));
            tvNumberOfStarts5.setText(ratings.votes.get(0).count.toString());
            progressBarRating4.setProgress(getPercentage(numberVotes, ratings.votes.get(1).count));
            tvNumberOfStarts4.setText(ratings.votes.get(1).count.toString());
            progressBarRating3.setProgress(getPercentage(numberVotes, ratings.votes.get(2).count));
            tvNumberOfStarts3.setText(ratings.votes.get(2).count.toString());
            progressBarRating2.setProgress(getPercentage(numberVotes, ratings.votes.get(3).count));
            tvNumberOfStarts2.setText(ratings.votes.get(3).count.toString());
            progressBarRating1.setProgress(getPercentage(numberVotes, ratings.votes.get(4).count));
            tvNumberOfStarts1.setText(ratings.votes.get(4).count.toString());
        }

        private void populatePermissionsTable(final GetApp getApp) {
            String websiteAux;
            String emailAux;
            final String privacyAux;

            if (TextUtils.isEmpty(website)) {
                websiteAux = getString(R.string.na);
            } else {
                websiteAux = website;
                mWebsiteLabel.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (AptoideUtils.Algorithms.copyToClipBoard(getActivity(), website)) {
                            Toast.makeText(getActivity(), R.string.website_copied, Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
            if (TextUtils.isEmpty(email)) {
                emailAux = getString(R.string.na);
            } else {
                emailAux = email;
                mEmailLabel.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (AptoideUtils.Algorithms.copyToClipBoard(getActivity(), email)) {
                            Toast.makeText(getActivity(), R.string.email_copied, Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
            if (TextUtils.isEmpty(privacy)) {
                privacyAux = getString(R.string.na);
            } else {
                privacyAux = privacy;
                mPrivacyLabel.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (AptoideUtils.Algorithms.copyToClipBoard(getActivity(), privacyAux)) {
                            Toast.makeText(getActivity(), R.string.privacy_copied, Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
            //        if (TextUtils.isEmpty(email)) {
            //            email = getString(R.string.na);
            //        }
            //        if (TextUtils.isEmpty(privacy)) {
            //            privacy = getString(R.string.na);
            //        }

            mWebsiteLabel.setText(Html.fromHtml(
                    AptoideUtils.StringUtils.getFormattedString(getActivity(), R.string.website, websiteAux)));
            mEmailLabel.setText(Html.fromHtml(
                    AptoideUtils.StringUtils.getFormattedString(getActivity(), R.string.email, emailAux)));
            mPrivacyLabel.setText(Html.fromHtml(AptoideUtils.StringUtils.getFormattedString(getActivity(),
                    R.string.privacy_policy, privacyAux)));
            if (getApp == null || getApp.nodes == null || getApp.nodes.meta == null
                    || getApp.nodes.meta.data == null || getApp.nodes.meta.data.file == null
                    || getApp.nodes.meta.data.file.usedPermissions == null
                    || getApp.nodes.meta.data.file.usedPermissions.isEmpty()) {

                mPermissionsLabel.setText(getString(R.string.permissions_na));
            } else {

                mPermissionsLabel.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        DialogPermissions dialogPermissions = DialogPermissions.newInstance(getApp, appName,
                                versionName, iconUrl, AptoideUtils.StringUtils
                                        .formatBits(AptoideUtils.AppUtils.sumFileSizes(fileSize, obb)));
                        dialogPermissions.show(getChildFragmentManager(), "");
                    }
                });
            }
        }

        RequestListener<GetComments> requestCommentListener = new RequestListener<GetComments>() {
            @Override
            public void onRequestFailure(SpiceException spiceException) {
                Logger.printException(spiceException);
            }

            @Override
            public void onRequestSuccess(GetComments get) {
                forceReload = false;
                if (get != null && get.list != null) {

                    if (get.list.size() > MAX_VISIBLE_COMMENTS) {
                        mSeeMoreComments.setVisibility(View.VISIBLE);
                        mSeeMoreComments.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Intent i = new Intent(getActivity(), MoreCommentsActivity.class);
                                i.putExtra(Constants.STORENAME_KEY, storeName);
                                i.putExtra(Constants.PACKAGENAME_KEY, packageName);
                                i.putExtra(Constants.VERSIONNAME_KEY, versionName);
                                i.putExtra(Constants.EVENT_LABEL, appName); // The label is used to populate the title
                                // in the MoreActivity
                                startActivity(i);
                            }
                        });
                    }

                    displayableCommentsList.clear();
                    displayableCommentsList.add(new HeaderRow("Comments", false, bucketSize));

                    if (!get.list.isEmpty()) {

                        for (int i = 0; i < get.list.size() && i < MAX_VISIBLE_COMMENTS; i++) {
                            displayableCommentsList.add(LatestCommentsFragment.createComment(get.list.get(i)));
                        }

                        displayableCommentsList = LatestCommentsFragment.sortComments(displayableCommentsList);

                    } else {
                        displayableCommentsList.add(new NoCommentPlaceHolderRow(bucketSize));
                    }

                    CommentsStoreAdapter adapter = new CommentsStoreAdapter(displayableCommentsList, getActivity(),
                            getResources().getColor(EnumStoreTheme.APTOIDE_STORE_THEME_DEFAULT.getStoreHeader()),
                            true, addCommentCallback);

                    recyclerComments.addItemDecoration(new RecyclerView.ItemDecoration() {
                        @Override
                        public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
                                RecyclerView.State state) {
                            outRect.set(recyclerOffset, recyclerOffset, recyclerOffset, 0);
                        }
                    });
                    recyclerComments.setLayoutManager(new WrappingLinearLayoutManager(getActivity()));
                    recyclerComments.setNestedScrollingEnabled(false);
                    recyclerComments.setAdapter(adapter);
                }
            }
        };

        AddCommentCallback addCommentCallback = new AddCommentCallback() {
            @Override
            public void addComment(String comment, String answerTo) {
                if (comment != null && comment.length() < Constants.MIN_COMMENT_CHARS) {
                    Toast.makeText(getActivity(), R.string.error_IARG_100, Toast.LENGTH_LONG).show();
                    return;
                }

                AddCommentRequest request = new AddCommentRequest(getActivity());
                request.setApkversion(versionName);
                request.setPackageName(packageName);
                request.setRepo(storeName);
                request.setText(comment);

                if (answerTo != null) {
                    request.setAnswearTo(answerTo);
                }

                spiceManager.execute(request, addCommentRequestListener);
                AptoideDialog.pleaseWaitDialog().show(getChildFragmentManager(), "pleaseWaitDialog");
            }
        };

        RequestListener<GenericResponseV2> addCommentRequestListener = new AlmostGenericResponseV2RequestListener() {
            @Override
            public void CaseOK() {
                Toast.makeText(getActivity(), getString(R.string.comment_submitted), Toast.LENGTH_LONG).show();
                refresh();
                dismissDialog();
            }

            @Override
            public void onRequestFailure(SpiceException spiceException) {
                super.onRequestFailure(spiceException);
                dismissDialog();
            }

            @Override
            public void onRequestSuccess(GenericResponseV2 genericResponse) {
                super.onRequestSuccess(genericResponse);
                dismissDialog();
            }

            protected void dismissDialog() {
                DialogFragment pd = (DialogFragment) getChildFragmentManager()
                        .findFragmentByTag("pleaseWaitDialog");
                if (pd != null) {
                    pd.dismissAllowingStateLoss();
                }
            }
        };

        View.OnClickListener badgeClickListener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AptoideDialog.badgeDialogV7(malware, appName, malware.rank).show(getFragmentManager(),
                        BADGE_DIALOG_TAG);
            }
        };

        private View.OnClickListener extendListener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                extendSeeMore();
            }
        };

        /**
         * Callback when dismissing MyAppInstallDialog
         */
        DialogInterface.OnDismissListener onDismissListener = new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {

                if (!new AptoideDatabase(Aptoide.getDb()).existsRepo(storeName)) {
                    AptoideDialog
                            .addMyAppStore("http://" + storeName + ".store.aptoide.com/", appsAddStoreInterface)
                            .show(getChildFragmentManager(), "myAppStore");
                }
            }
        };

        /**
         * Callback to be provided to a Dialog in order to add a store
         */
        MyAppStoreDialog.MyAppsAddStoreInterface appsAddStoreInterface = new MyAppStoreDialog.MyAppsAddStoreInterface() {
            @Override
            public DialogInterface.OnClickListener getOnMyAppAddStoreListener(final String repo) {
                return new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Store store = new Store();
                        store.setBaseUrl(AptoideUtils.RepoUtils.formatRepoUri(repo));
                        store.setName(AptoideUtils.RepoUtils.split(repo));
                        AptoideUtils.RepoUtils.startParse(store.getName(), getActivity(), spiceManager);
                    }
                };
            }
        };

        private void updateFlags(GetApp getApp) {

            if (getApp == null || getApp.nodes == null || getApp.nodes.meta == null
                    || getApp.nodes.meta.data == null || getApp.nodes.meta.data.file == null
                    || getApp.nodes.meta.data.file.flags == null) {
                return;
            }

            GetAppMeta.File.Flags flags = getApp.nodes.meta.data.file.flags;

            if (GetAppMeta.File.Flags.GOOD.equals(flags.review)) {
                mFlagsLayout.setVisibility(View.GONE);
                mButtonFlagThisApp.setVisibility(View.GONE);
                manualReviewLayout.setVisibility(View.VISIBLE);

            } else {
                manualReviewLayout.setVisibility(View.GONE);
                mFlagsLayout.setVisibility(View.VISIBLE);
                mButtonFlagThisApp.setVisibility(View.VISIBLE);
                mButtonFlagThisApp.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (AptoideUtils.AccountUtils.isLoggedIn(getActivity())) {
                            AptoideDialog.flagAppDialog(userVote).show(getChildFragmentManager(), "flagAppDialog");
                        } else {
                            Intent intent = new Intent(getActivity(), MyAccountActivity.class);
                            getActivity().startActivity(intent);
                        }
                    }
                });
                if (flags.votes != null) {
                    for (GetAppMeta.File.Flags.Vote vote : flags.votes) {
                        Number numberVotes = vote.count;
                        if (vote.type.toUpperCase().equals(GetAppMeta.File.Flags.Vote.GOOD)) {
                            tvNumberGoodFlags.setText(String.valueOf(numberVotes));
                        } else if (vote.type.toUpperCase().equals(GetAppMeta.File.Flags.Vote.FREEZE)) {
                            tvNumberFreezeFlags.setText(String.valueOf(numberVotes));
                        } else if (vote.type.toUpperCase().equals(GetAppMeta.File.Flags.Vote.FAKE)) {
                            tvNumberFakeFlags.setText(String.valueOf(numberVotes));
                        } else if (vote.type.toUpperCase().equals(GetAppMeta.File.Flags.Vote.LICENSE)) {
                            tvNumberLicenceFlags.setText(String.valueOf(numberVotes));
                        } else if (vote.type.toUpperCase().equals(GetAppMeta.File.Flags.Vote.VIRUS)) {
                            tvNumberVirusFlags.setText(String.valueOf(numberVotes));
                        }
                    }
                }
            }
        }

        private void updateBadges() {
            if (malware == null || malware.rank == null) {
                return;
            }

            badgeLayout.setOnClickListener(badgeClickListener);

            switch (malware.rank) {
            case TRUSTED:
                mTrustedLayout.setVisibility(View.VISIBLE);
                mTrustedLayout.setOnClickListener(badgeClickListener);

                break;
            case WARNING:
                mWarningLayout.setVisibility(View.VISIBLE);
                mWarningLayout.setOnClickListener(badgeClickListener);

                break;
            case UNKNOWN:
                mUnknownLayoutt.setVisibility(View.VISIBLE);
                mUnknownLayoutt.setOnClickListener(badgeClickListener);
                break;
            }

            if (malware.reason != null) {

                if (malware.reason.thirdpartyValidated != null && GetAppMeta.File.Malware.GOOGLE_PLAY
                        .equalsIgnoreCase(malware.reason.thirdpartyValidated.store)) {
                    mBadgeMarket.setVisibility(View.VISIBLE);
                }

                if (malware.reason.signatureValidated != null
                        && GetAppMeta.File.Malware.PASSED.equals(malware.reason.signatureValidated.status)) {
                    mBadgeSignature.setVisibility(View.VISIBLE);
                }

                if (malware.reason.scanned != null
                        && GetAppMeta.File.Malware.PASSED.equals(malware.reason.scanned.status)) {
                    mBadgeAntiVirus.setVisibility(View.VISIBLE);
                }

                if (malware.reason.manualQA != null
                        && GetAppMeta.File.Malware.PASSED.equals(malware.reason.manualQA.status)) {
                    mBadgeFlag.setVisibility(View.VISIBLE);
                }
            }
        }

        private void updateStoreInfo() {

            final Context context = getActivity();
            if (TextUtils.isEmpty(storeAvatar)) {
                glide.fromResource().load(R.drawable.ic_avatar_apps).transform(new CircleTransform(context))
                        .into(mStoreAvatar);
            } else {
                glide.load(storeAvatar).bitmapTransform(new CircleTransform(context)).into(mStoreAvatar);
            }

            mStoreName.setText(storeName);
            mStoreName.setTextColor(getResources().getColor(storeTheme.getStoreHeader()));
            mStoreUsers.setText(String.valueOf(storeSubscribers));
            if (Build.VERSION.SDK_INT > 10) {
                mButtonSubscribe.setBackgroundDrawable(getResources().getDrawable(storeTheme.getButtonLayout()));
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    mButtonSubscribe.setElevation(0);
                }
            }
            mButtonSubscribe.setTextColor(getResources().getColor(storeTheme.getStoreHeader()));

            OpenStoreOnClickListener openStoreOnClickListener = new OpenStoreOnClickListener();
            mStoreView.setOnClickListener(openStoreOnClickListener);

            final boolean subscribed = new AptoideDatabase(Aptoide.getDb()).existsStore(storeId);
            if (subscribed) {
                int checkmarkDrawable = storeTheme.getCheckmarkDrawable();
                mButtonSubscribe.setCompoundDrawablesWithIntrinsicBounds(checkmarkDrawable, 0, 0, 0);
                mButtonSubscribe.setText(getString(R.string.appview_subscribed_store_button_text));
                mButtonSubscribe.setOnClickListener(openStoreOnClickListener);

            } else {
                int plusMarkDrawable = storeTheme.getPlusmarkDrawable();
                mButtonSubscribe.setCompoundDrawablesWithIntrinsicBounds(plusMarkDrawable, 0, 0, 0);
                mButtonSubscribe.setText(getString(R.string.appview_subscribe_store_button_text));
                mButtonSubscribe.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        AptoideUtils.RepoUtils.startParse(storeName, getActivity(), spiceManager);
                    }
                });
            }
        }

        class OpenStoreOnClickListener implements View.OnClickListener {

            @Override
            public void onClick(View v) {
                reloadButtons = true;
                final Context context = getActivity();
                final Intent intent = StoresActivity.newIntent(context, storeId, storeName, storeAvatar,
                        storeTheme.ordinal());
                intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
                context.startActivity(intent);
            }
        }

        private void updateUI() {

            if (graphic != null) {
                glide.load(graphic).into(mFeaturedGraphic);
            } else if (screenshots != null && screenshots.size() > 0
                    && !TextUtils.isEmpty(screenshots.get(0).url)) {
                glide.load(screenshots.get(0).url).into(mFeaturedGraphic);
            }

            if (iconUrl != null) {
                glide.load(iconUrl).into(mAppIcon);
            }

            mVersionName.setText(versionName);
            mDownloadsNumber.setText(AptoideUtils.StringUtils.withSuffix(downloads));
            mFileSize.setText(
                    AptoideUtils.StringUtils.formatBits(AptoideUtils.AppUtils.sumFileSizes(fileSize, obb)));
            mRatingBarTop.setRating(rating);
            mCollapsingToolbarLayout.setTitle(appName);
        }

        private void populateMoreVersions(GetAppModel model) {
            GetApp getApp = model.getApp;
            mMoreVersionsList.setNestedScrollingEnabled(false);

            /**
             * If the size of the list is 1, it means it's the own app and should be removed.
             */
            if (getApp == null || getApp.nodes == null || getApp.nodes.versions == null
                    || getApp.nodes.versions.list == null || getApp.nodes.versions.list.size() < 2) {

                mMoreVersionsLayoutHeader.setVisibility(View.GONE);
                mMoreVersionsList.setVisibility(View.GONE);
                return;
            }

            mMoreVersionsLayoutButton.setClickable(false);
            mMoreVersionsLayoutHeader.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    Intent intent = new Intent(getActivity(), MoreVersionsActivity.class);
                    intent.putExtra(Constants.PACKAGENAME_KEY, packageName);
                    intent.putExtra(Constants.EVENT_LABEL, appName);
                    startActivity(intent);
                }
            });

            mMoreVersionsTitle.setText(R.string.appview_other_versions_in_others_stores);

            // AN-227: remove the first app if it's the same as this
            if (!model.list.isEmpty() && model.list.get(0).versionCode == versionCode) {

                model.list.remove(0);
            }

            // Moar hack: only use one row
            List<MoreVersionsAppViewItem> list = new ArrayList<>();
            for (int i = 0; i < model.list.size() && i < bucketSize; i++) {
                list.add(model.list.get(i));
            }

            MoreAppViewVersionsAdapter adapter = new MoreAppViewVersionsAdapter(list);

            mMoreVersionsList.setAdapter(adapter);
            final short recyclerViewOffset = (short) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5,
                    getResources().getDisplayMetrics());
            mMoreVersionsList.addItemDecoration(new RecyclerView.ItemDecoration() {
                @Override
                public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
                    outRect.set(recyclerViewOffset, recyclerViewOffset, recyclerViewOffset, recyclerViewOffset);
                }
            });

            GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), bucketSize);
            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {

                    if (!(mMoreVersionsList.getAdapter() instanceof SpannableRecyclerAdapter)) {
                        throw new IllegalStateException(
                                "RecyclerView adapter must extend SpannableRecyclerAdapter");
                    }

                    return AptoideUtils.UI.getSpanSize(mMoreVersionsList, position);
                }
            });

            gridLayoutManager.setSpanCount(bucketSize);

            mMoreVersionsList.setLayoutManager(gridLayoutManager);
        }

        private void setupInstallButton() {
            setBtnState();
            BtnInstallState state = (BtnInstallState) mButtonInstall.getTag();
            switch (state) {
            case BUY:
                changebtInstalltoBuy();
                mButtonInstall.setVisibility(View.GONE);
                break;
            case DOWNGRADE:
                mButtonInstall.setText(R.string.downgrade);
                break;
            case UPDATE:
                mButtonInstall.setText(R.string.update);
                break;
            case INSTALL:
                mButtonInstall.setText(R.string.install);
                break;
            case OPEN:
                mButtonInstall.setText(R.string.open);
                changebtInstalltoOpen();
                break;
            }
        }

        private void changebtInstalltoBuy() {

            GetApkInfoRequestFromId getApkInfoRequestFromId = new GetApkInfoRequestFromId(getActivity());
            getApkInfoRequestFromId.setAppId(Long.toString(appId));

            spiceManager.execute(getApkInfoRequestFromId, getApkInfoJsonRequestListener);
        }

        public void setBtnState() {
            PackageInfo info = getPackageInfo(getActivity(), packageName);
            //check if the app is installed
            if (info == null) {
                //check if the app is payed
                if (pay != null && pay.price.doubleValue() > 0) {
                    mButtonInstall.setTag(BtnInstallState.BUY);
                } else {
                    mButtonInstall.setTag(BtnInstallState.INSTALL);
                }
            } else {
                if (versionCode > info.versionCode) {
                    mButtonInstall.setTag(BtnInstallState.UPDATE);
                } else if (versionCode < info.versionCode) {
                    mButtonInstall.setTag(BtnInstallState.DOWNGRADE);
                } else {
                    mButtonInstall.setTag(BtnInstallState.OPEN);
                }
            }
        }

        private void checkInstallation() {
            mButtonInstall.setEnabled(true);
            if (pay != null && pay.price.doubleValue() > 0) {
                isPaidToschedule = true;
                //                mButtonInstall.setVisibility(View.GONE);
                InstallListener installListener = new InstallListener(iconUrl, appName, versionName, packageName,
                        md5sum, isPaidApp());
                mButtonInstall.setOnClickListener(installListener);
            } else {
                PackageInfo info = getPackageInfo(getActivity(), packageName);
                if (info == null) {
                    mButtonInstall.setText(getString(R.string.install));
                    mButtonInstall.setOnClickListener(
                            new InstallListener(iconUrl, appName, versionName, packageName, md5sum, isPaidApp()));
                    isInstalled = false;
                } else {
                    isInstalled = true;
                    try {
                        installedSignature = AptoideUtils.Algorithms
                                .computeSHA1sumFromBytes(info.signatures[0].toByteArray())
                                .toUpperCase(Locale.ENGLISH);
                    } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
                        Logger.printException(e);
                    }
                    if (versionCode > info.versionCode) {
                        isUpdate = true;
                        mButtonInstall.setText(getString(R.string.update));
                        mButtonInstall.setEnabled(true);
                        mButtonInstall.setOnClickListener(new InstallListener(iconUrl, appName, versionName,
                                packageName, md5sum, isPaidApp()));
                        //                    UpdateAppVersionInstalled(info.versionName);
                    } else if (versionCode < info.versionCode) {
                        isUpdate = false;
                        mButtonInstall.setText(getString(R.string.downgrade));
                        mButtonInstall.setOnClickListener(new DowngradeListener(iconUrl, appName, info.versionName,
                                versionName, info.packageName));
                        //                    UpdateAppVersionInstalled(info.versionName);
                    } else {
                        changebtInstalltoOpen();
                    }
                    getActivity().supportInvalidateOptionsMenu();
                }
            }

            setupInstallButton();
        }

        private void changebtInstalltoOpen() {
            final Intent i = getActivity().getPackageManager().getLaunchIntentForPackage(packageName);
            mButtonInstall.setText(getString(R.string.open));
            if (i != null) {
                mButtonInstall.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        try {
                            startActivity(i);
                        } catch (ActivityNotFoundException e) {
                            Logger.printException(e);
                        }
                    }
                });
            } else {
                mButtonInstall.setEnabled(false);
            }
        }

        /**
         * Changes maxLines of the description textView. Needs to be synchronized because it can be
         * called simultaneously on two different views.
         */
        public synchronized void extendSeeMore() {

            /** The MAX_LINES parameter cannot be too long, or the animation will not be seen smoothly */
            final int MAX_LINES = 200;
            final int ANIMATION_DELAY = 0;
            int maxLines;
            int[] values;
            String text;

            if (extended) {
                maxLines = descriptionLines;
                values = new int[] { MAX_LINES, maxLines };
                text = getString(R.string.see_more);
                mArrow.setImageDrawable(getResources().getDrawable(R.drawable.ic_down_arrow));
            } else {
                maxLines = MAX_LINES;
                values = new int[] { descriptionLines, maxLines };
                text = getString(R.string.see_less);
                mArrow.setImageDrawable(getResources().getDrawable(R.drawable.ic_up_arrow));
            }

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                ObjectAnimator animation = ObjectAnimator.ofInt(mDescription, "maxLines", values);
                animation.setDuration(ANIMATION_DELAY).start();
            } else {
                mDescription.setMaxLines(maxLines);
            }

            if (extended) {
                mContentView.scrollTo(0, scrollPosition);
            } else {
                scrollPosition = mDescription.getLeft();
            }

            mSeeMore.setText(text);
            extended = !extended;
        }

        private void getOrganicAds() {
            if (lifecycleController) {
                return;
            }

            final GetAdsRequest getAdsRequest = new GetAdsRequest("", false);

            getAdsRequest.setLocation("appview");
            getAdsRequest.setKeyword("__NULL__");
            getAdsRequest.setRepo(storeName);
            getAdsRequest.setPackage_name(packageName);
            getAdsRequest.setLimit(1);
            getAdsRequest.setRetryPolicy(new RetryPolicy() {
                @Override
                public int getRetryCount() {
                    return 0;
                }

                @Override
                public void retry(SpiceException e) {
                }

                @Override
                public long getDelayBeforeRetry() {
                    return 0;
                }
            });
            getAdsRequest.setTimeout(2000);

            spiceManager.execute(getAdsRequest, new RequestListener<ApkSuggestionJson>() {
                @Override
                public void onRequestFailure(SpiceException spiceException) {
                }

                @Override
                public void onRequestSuccess(ApkSuggestionJson apkSuggestionJson) {
                    try {

                        ApkSuggestionJson.Ads appSuggested = apkSuggestionJson.getAds().get(0);

                        if (apkSuggestionJson.getAds().size() == 0) {
                            return;
                        }
                        if (appSuggested.getPartner() == null) {
                            return;
                        }
                        if (appSuggested.getPartner().getPartnerData() == null) {
                            return;
                        }

                        appSuggested = apkSuggestionJson.getAds().get(0);

                        String clickUrl = appSuggested.getPartner().getPartnerData().getClick_url();
                        final String adPackageName = appSuggested.getData().getPackageName();
                        long id = appSuggested.getData().getId().longValue();
                        adId = appSuggested.getInfo().getAd_id();

                        ReferrerUtils.extractReferrer(packageName, appId, adId, -1, clickUrl, spiceManager, null,
                                ReferrerUtils.RETRIES);

                        OkHttpClient client = new OkHttpClient();

                        Request cpc_click = new Request.Builder().url(appSuggested.getInfo().getCpc_url()).build();

                        client.newCall(cpc_click).enqueue(new Callback() {
                            @Override
                            public void onFailure(Request request, IOException e) {
                            }

                            @Override
                            public void onResponse(Response response) throws IOException {
                            }
                        });

                        Intent intent = getActivity().getIntent();
                        intent.putExtra("cpi", appSuggested.getInfo().getCpi_url());
                        getActivity().setIntent(intent);
                    } catch (Exception e) {
                        Logger.printException(e);
                    }
                }
            });
        }

        @Subscribe
        public void refreshStoresEvent(OttoEvents.RepoAddedEvent event) {
            Toast.makeText(getActivity(), AptoideUtils.StringUtils.getFormattedString(getActivity(),
                    com.aptoide.amethyst.R.string.store_subscribed, storeName), Toast.LENGTH_SHORT).show();
            updateStoreInfo();
        }

        @Subscribe
        public void onDownloadEventUpdate(OttoEvents.DownloadEvent download) {
            if (downloadService != null && download.getId() == downloadId) {
                onDownloadUpdate(downloadService.getDownload(download.getId()).getDownload());
            }
        }

        @Subscribe
        public void onInstalledEvent(OttoEvents.InstalledApkEvent event) {
            refresh();
        }

        @Subscribe
        public void onUnInstalledEvent(OttoEvents.UnInstalledApkEvent event) {
            refresh();
        }

        @Subscribe
        public void onRefresh(OttoEvents.AppViewRefresh event) {
            refresh();
        }

        @Subscribe
        public void onDownloadUpdate(OttoEvents.DownloadInProgress event) {
            if (event != null) {
                Download download = event.getDownload();
                onDownloadUpdate(download);
            }
        }

        private void refresh() {
            forceReload = true;
            executeSpiceRequestWithAppId(appId, storeName, packageName);
        }

        /**
         * Hides the layout with the install button and shows the download progress bar.
         * Creates a {@link Download} object and send it to the {@link DownloadService}
         *
         */
        private void download() {
            this.showRootDialog();

            Download download = new Download();
            download.setId(downloadId);
            download.setName(appName);
            download.setVersion(versionName);
            download.setIcon(iconUrl);
            download.setPackageName(packageName);
            download.setMd5(md5sum);
            download.setPaid(isPaidApp());

            if (!isUpdate) {
                download.setCpiUrl(getActivity().getIntent().getStringExtra("cpi"));
            }
            try {
                //TODO Main thread synchronization
                downloadServiceLatch.await();
            } catch (InterruptedException e) {
                Logger.printException(e);
            }
            if (downloadService == null) {
                return;
            }
            downloadService.downloadFromV7WithObb(path, altPath, md5sum, fileSize, appName, packageName,
                    versionName, iconUrl, appId, pay != null, obb, download, permissions);

            isFromActivityResult = false;
            autoDownload = false;

            populateDownloadUI();
        }

        private void onDownloadUpdate(Download download) {
            if (download != null && download.getId() == downloadId) {
                mInstallAndLatestVersionLayout.setVisibility(View.GONE);
                mDownloadProgressLayout.setVisibility(View.VISIBLE);

                switch (download.getDownloadState()) {
                case ACTIVE:
                    mActionResume.setVisibility(View.GONE);
                    mDownloadingProgress.setIndeterminate(false);
                    mDownloadingProgress.setProgress(download.getProgress());
                    mProgressText.setText(download.getProgress() + "% - "
                            + AptoideUtils.StringUtils.formatBits((long) download.getSpeed()) + "/s");
                    break;
                case INACTIVE:
                    break;
                case COMPLETE:
                    mInstallAndLatestVersionLayout.setVisibility(View.VISIBLE);
                    mDownloadProgressLayout.setVisibility(View.GONE);
                    break;
                case PENDING:
                    mActionResume.setVisibility(View.GONE);
                    mDownloadingProgress.setIndeterminate(false);
                    mDownloadingProgress.setProgress(download.getProgress());
                    mProgressText.setText(getString(R.string.download_pending));
                    break;
                case ERROR:
                    mActionResume.setVisibility(View.VISIBLE);
                    mProgressText.setText(download.getDownloadState().name());
                    mDownloadingProgress.setIndeterminate(false);
                    mDownloadingProgress.setProgress(download.getProgress());
                    break;
                }
            }
        }

        private void setShareTimeLineButton() {
            final CheckBox btinstallshare = (CheckBox) getView().findViewById(R.id.btinstallshare);
            if (Preferences.getBoolean(Preferences.TIMELINE_ACEPTED_BOOL, false)) {
                btinstallshare.setVisibility(View.VISIBLE);
                btinstallshare.setChecked(Preferences.getBoolean(Preferences.SHARE_TIMELINE_DOWNLOAD_BOOL, true));
                btinstallshare.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        final Map<String, String> shareTimelineParams = new HashMap<String, String>();
                        shareTimelineParams.put("Share_Timeline", String.valueOf(isChecked));
                        FlurryAgent.logEvent("App_View_Clicked_On_Share_Timeline_Checkbox", shareTimelineParams);
                        Preferences.putBooleanAndCommit(Preferences.SHARE_TIMELINE_DOWNLOAD_BOOL, isChecked);
                    }
                });
            } else {
                btinstallshare.setVisibility(View.INVISIBLE);
            }
        }

        private void populateDownloadUI() {
            setShareTimeLineButton();

            getView().findViewById(R.id.ic_action_cancel).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    if (downloadService != null) {
                        FlurryAgent.logEvent("App_View_Canceled_Download");
                        downloadService.stopDownload(downloadId);
                    }

                }
            });

            getView().findViewById(R.id.ic_action_resume).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    if (downloadService != null) {
                        downloadService.resumeDownload(downloadId);
                    }
                }
            });

            if (downloadService != null && downloadService.getDownload(downloadId).getDownload() != null) {
                onDownloadUpdate(downloadService.getDownload(downloadId).getDownload());
            }

            if (refreshOnResume) {
                spiceManager.removeDataFromCache(GetApkInfoJson.class);
                refreshOnResume = false;
            }

        }

        /**
         * Will create the views that show images and video screenshots.
         */
        private void populateScreenShotsView() {
            ArrayList<IMediaObject> mediaObjects = new ArrayList<>();

            if (videos != null) {
                // Add Videos' screenshots first
                for (GetAppMeta.Media.Video video : videos) {
                    mediaObjects.add(new Video(video.thumbnail, video.url));
                }
            }

            if (screenshots != null) {
                for (GetAppMeta.Media.Screenshot screenshot : screenshots) {
                    mediaObjects.add(new Screenshot(screenshot.url, screenshot.getOrientation()));
                }
            }

            ScreenshotsAdapter adapter = new ScreenshotsAdapter(glide, mediaObjects);
            mScreenshotsList.addItemDecoration(new DividerItemDecoration(AptoideUtils.getPixels(getActivity(), 5)));
            mScreenshotsList.setLayoutManager(
                    new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false));
            mScreenshotsList.setNestedScrollingEnabled(false); // because otherwise the AppBar won't be collapsed
            mScreenshotsList.setAdapter(adapter);

            if (mediaObjects.isEmpty()) {
                mScreenshotsList.setVisibility(View.GONE);
            }
        }

        private boolean isPaidApp() {
            return pay != null && pay.price.doubleValue() > 0;
        }

        private void handleErrorCondition(Exception e) {

            Logger.printException(e);
            mProgressBar.setVisibility(View.GONE);
            mAppBarLayout.setVisibility(View.GONE);
            mContentView.setVisibility(View.GONE);

            if (e != null && e.getCause() != null && e.getCause().getMessage() != null
                    && e.getCause().getMessage().equals(APP_NOT_AVAILABLE)) {
                layoutError410.setVisibility(View.VISIBLE);
                Toolbar mToolbar = (Toolbar) getView().findViewById(R.id.toolbar_410);
                final AppViewActivity activity = (AppViewActivity) getActivity();
                activity.setSupportActionBar(mToolbar);
                ActionBar supportActionBar = activity.getSupportActionBar();
                if (supportActionBar != null) {
                    supportActionBar.setTitle("Aptoide");
                    supportActionBar.setHomeButtonEnabled(true);
                    supportActionBar.setDisplayHomeAsUpEnabled(true);
                }
            } else if (e instanceof NoNetworkException) {
                layoutError.setVisibility(View.GONE);
                layoutNoNetwork.setVisibility(View.VISIBLE);
                retryNoNetwork.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if (mProgressBar != null && layoutNoNetwork != null) {
                            mProgressBar.setVisibility(View.VISIBLE);
                            layoutNoNetwork.setVisibility(View.GONE);
                        }
                        refresh();
                    }
                });
            } else {
                showGenericError();
            }
        }

        private void handleSuccessCondition() {
            mContentView.setVisibility(View.VISIBLE);
            mProgressBar.setVisibility(View.GONE);

            layoutError.setVisibility(View.GONE);
            layoutNoNetwork.setVisibility(View.GONE);
            mAppBarLayout.setVisibility(View.VISIBLE);
            mContentView.setVisibility(View.VISIBLE);
        }

        private void showGenericError() {
            layoutNoNetwork.setVisibility(View.GONE);
            layoutError.setVisibility(View.VISIBLE);
            retryError.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (mProgressBar != null && layoutError != null) {
                        mProgressBar.setVisibility(View.VISIBLE);
                        layoutError.setVisibility(View.GONE);
                    }
                    refresh();
                }
            });
        }

        private void handleLatestVersionLogic() {
            if (latestAvailable) {

                mLatestVersionLayout.setVisibility(View.GONE);
                mButtonUninstall.setVisibility(View.GONE);
                mButtonGetLatest.setVisibility(View.VISIBLE);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    mButtonGetLatest.setElevation(0);
                }
                mButtonGetLatest.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Intent i = new Intent(getActivity(), AppViewActivity.class);
                        i.putExtra(Constants.FROM_RELATED_KEY, true);
                        i.putExtra(Constants.APP_ID_KEY, latestAppId);
                        i.putExtra(Constants.APPNAME_KEY, appName);
                        i.putExtra(Constants.PACKAGENAME_KEY, packageName);
                        i.putExtra(Constants.DOWNLOAD_FROM_KEY, "app_view_more_multiversion");
                        startActivity(i);
                    }
                });
            } else if (isInstalled) {
                mButtonGetLatest.setVisibility(View.GONE);
                mLatestVersionLayout.setVisibility(View.GONE);
                mButtonUninstall.setVisibility(View.VISIBLE);
                mButtonUninstall.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        reloadButtons = true;
                        Fragment uninstallFragment = new UninstallRetainFragment();
                        Bundle args = new Bundle();
                        args.putString("name", appName);
                        args.putString("package", packageName);
                        args.putString("version", versionName);
                        args.putString("icon", iconUrl);
                        uninstallFragment.setArguments(args);
                        getFragmentManager().beginTransaction().add(uninstallFragment, "uninstallFrag").commit();
                    }
                });
            } else {
                mButtonUninstall.setVisibility(View.GONE);
                mButtonGetLatest.setVisibility(View.GONE);
                mLatestVersionLayout.setVisibility(View.VISIBLE);
            }
        }

        @Override
        public void addApkFlagClick(String flag) {

            final DialogFragment dialogFragment = AptoideDialog.pleaseWaitDialog();
            dialogFragment.show(getChildFragmentManager(), "pleaseWaitDialog");

            AddApkFlagRequest flagRequest = new AddApkFlagRequest();
            flagRequest.setRepo(storeName);
            flagRequest.setMd5sum(md5sum);
            flagRequest.setFlag(flag);
            userVote = flag;
            spiceManager.execute(AptoideUtils.RepoUtils.buildFlagAppRequest(storeName, flag, md5sum),
                    new RequestListener<GenericResponseV2>() {
                        @Override
                        public void onRequestFailure(SpiceException spiceException) {
                            dialogFragment.dismiss();
                        }

                        @Override
                        public void onRequestSuccess(GenericResponseV2 genericResponseV2) {
                            if (genericResponseV2.getStatus().toUpperCase().equals("OK")) {
                                BusProvider.getInstance().post(new OttoEvents.AppViewRefresh());
                                Toast.makeText(getActivity(), R.string.flag_added, Toast.LENGTH_SHORT).show();
                            } else {
                                Toast.makeText(getActivity(), R.string.error_occured, Toast.LENGTH_SHORT).show();
                            }
                            spiceManager.removeDataFromCache(GetApp.class, md5sum);
                            try {
                                dialogFragment.dismiss();
                            } catch (Exception e) {
                                Logger.e(TAG, e.getMessage());
                            }
                        }
                    });
        }

        @Override
        public void voteComment(int commentId, AddApkCommentVoteRequest.CommentVote vote) {
            RequestListener<GenericResponseV2> commentRequestListener = new AlmostGenericResponseV2RequestListener() {
                @Override
                public void CaseOK() {
                    Toast.makeText(getActivity(), getString(R.string.vote_submitted), Toast.LENGTH_LONG).show();
                }
            };

            AptoideUtils.VoteUtils.voteComment(spiceManager, commentId, storeName,
                    SecurePreferences.getInstance().getString("token", "empty"), commentRequestListener, vote);
        }

        private void showRootDialog() {
            if (!PreferenceManager.getDefaultSharedPreferences(getActivity()).contains("allowRoot")
                    && !Aptoide.IS_SYSTEM) {
                final Handler handler = new Handler(Looper.getMainLooper());
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        if (AptoideUtils.AppUtils.isRooted()) {
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    // in a try because we might be already out of this Activity
                                    try {
                                        AptoideDialog.allowRootDialog().show(getChildFragmentManager(),
                                                "allowRoot");
                                    } catch (Exception e) {
                                        Logger.printException(e);
                                    }
                                }
                            });
                        }
                    }
                }).start();
            }
        }

        private void showDialogIfComingFromBrowser() {
            if (getActivity().getIntent().getBooleanExtra(Constants.FROM_MY_APP_KEY, false) && !isPaidApp()) {
                final InstallListener installListener = new InstallListener(iconUrl, appName, versionName,
                        packageName, md5sum, isPaidApp());
                DialogFragment dialog = AptoideDialog.myAppInstall(appName, installListener, onDismissListener);
                AptoideDialog.showDialogAllowingStateLoss(dialog, getChildFragmentManager(), "myApp");
            }
        }

        private void requestComments(boolean useCache) {
            long cacheExpiryDuration = (useCache || !forceReload) ? DurationInMillis.ONE_HOUR * 6
                    : DurationInMillis.ALWAYS_EXPIRED;

            // call list apkcomments, which need: storeName, packageName, versionName
            // http://webservices.aptoide.com/webservices/2/listApkComments/apps/com.android.vending/5.12.9/json
            AllCommentsRequest request = new AllCommentsRequest();

            request.storeName = storeName;
            request.versionName = versionName;
            request.packageName = packageName;
            request.filters = Aptoide.filters;
            request.limit = MAX_COMMENTS_REQUEST;
            request.lang = AptoideUtils.StringUtils.getMyCountryCode(getActivity());

            spiceManager.execute(request, "comments" + appName + appId + storeName + versionName + packageName,
                    cacheExpiryDuration, requestCommentListener);
        }

        private void continueLoading() {
            final Intent intent = getActivity().getIntent();
            if (intent.getBooleanExtra(Constants.FROM_RELATED_KEY, false)) {
                appId = intent.getLongExtra(Constants.APP_ID_KEY, 0);
                md5sum = intent.getStringExtra(Constants.MD5SUM_KEY);
                appName = intent.getStringExtra(Constants.APPNAME_KEY);
                iconUrl = intent.getStringExtra(Constants.ICON_KEY);
                downloads = intent.getLongExtra(Constants.DOWNLOADS_KEY, 0);
                rating = intent.getFloatExtra(Constants.RATING_KEY, 0.0f);
                graphic = intent.getStringExtra(Constants.GRAPHIC_KEY);
                fileSize = intent.getLongExtra(Constants.FILESIZE_KEY, 0);
                storeId = intent.getLongExtra(Constants.STOREID_KEY, 0);
                storeName = intent.getStringExtra(Constants.STORENAME_KEY);
                packageName = intent.getStringExtra(Constants.PACKAGENAME_KEY);
                versionName = intent.getStringExtra(Constants.VERSIONNAME_KEY);

                executeSpiceRequestWithAppId(appId, storeName, packageName);
            } else if (intent.getBooleanExtra(Constants.FROM_SPONSORED_KEY, false)) {
                fromSponsored = true;
                appId = intent.getLongExtra(Constants.APP_ID_KEY, -1);
                adId = intent.getLongExtra(Constants.AD_ID_KEY, -1);
                packageName = intent.getStringExtra(Constants.PACKAGENAME_KEY);
                storeName = intent.getStringExtra(Constants.STORENAME_KEY);
                appName = intent.getStringExtra(Constants.APPNAME_KEY);
                String location = intent.getStringExtra(Constants.LOCATION_KEY);
                String keyword = intent.getStringExtra(Constants.KEYWORD_KEY);
                String cpc = intent.getStringExtra(Constants.CPC_KEY);
                String cpi = intent.getStringExtra(Constants.CPI_KEY);
                cpd = intent.getStringExtra(Constants.CPD_KEY);
                String whereFrom = intent.getStringExtra(Constants.WHERE_FROM_KEY);
                download_from = intent.getStringExtra(Constants.DOWNLOAD_FROM_KEY);

                executeSpiceRequestWithAppId(appId, storeName, packageName);
                AptoideUtils.AdNetworks.knock(cpc);

                if (intent.hasExtra("partnerExtra")) {
                    final String clickUrl = intent.getBundleExtra("partnerExtra").getString("partnerClickUrl");
                    ReferrerUtils.extractReferrer(packageName, appId, adId, -1, clickUrl, spiceManager, null,
                            ReferrerUtils.RETRIES);
                }
            } else if (intent.getBooleanExtra(Constants.ROLLBACK_FROM_KEY, false)) {
                md5sum = intent.getStringExtra(Constants.MD5SUM_KEY);

                executeSpiceRequestWithMd5(md5sum, storeName);
            } else if (intent.getBooleanExtra(Constants.FROM_TIMELINE_KEY, false)) { // From Timeline
                appName = intent.getStringExtra(Constants.APPNAME_KEY);
                storeName = intent.getStringExtra(Constants.STORENAME_KEY);
                md5sum = intent.getStringExtra(Constants.MD5SUM_KEY);

                executeSpiceRequestWithMd5(md5sum, storeName);
            } else if (intent.getBooleanExtra(Constants.FROM_COMMENT_KEY, false)) {
                appId = intent.getLongExtra(Constants.APP_ID_KEY, 0);
                appName = intent.getStringExtra(Constants.APPNAME_KEY);

                executeSpiceRequestWithAppId(appId, storeName, null);
            } else if (intent.getBooleanExtra("fromApkInstaller", false)) {
                autoDownload = true;
                appId = intent.getLongExtra(Constants.APP_ID_KEY, 0);
                appName = intent.getStringExtra(Constants.APPNAME_KEY);
                storeName = intent.getStringExtra(Constants.STORENAME_KEY);
                packageName = intent.getStringExtra(Constants.PACKAGENAME_KEY);

                executeSpiceRequestWithAppId(appId, storeName, packageName);
            } else if (intent.getBooleanExtra(Constants.GET_BACKUP_APPS_KEY, false)) {
                packageName = Defaults.BACKUP_APPS_PACKAGE;
                appName = Defaults.BACKUP_APPS_NAME;

                executeSpiceRequestWithPackageName(packageName, appName);
            } else if (intent.getBooleanExtra(Constants.FROM_MY_APP_KEY, false)) { // from browser
                appId = intent.getLongExtra(Constants.APP_ID_KEY, 0);

                executeSpiceRequestWithAppId(appId, storeName, packageName);
            } else if (intent.getBooleanExtra(Constants.SEARCH_FROM_KEY, false)) { // from search inside app
                appName = intent.getStringExtra(Constants.APPNAME_KEY);
                md5sum = intent.getStringExtra(Constants.MD5SUM_KEY);
                storeName = intent.getStringExtra(Constants.STORENAME_KEY);

                executeSpiceRequestWithMd5(md5sum, storeName);
            } else if (intent.getBooleanExtra(Constants.UPDATE_FROM_KEY, false)) {
                iconUrl = intent.getStringExtra(Constants.ICON_KEY);
                appName = intent.getStringExtra(Constants.APPNAME_KEY);
                versionName = intent.getStringExtra(Constants.VERSIONNAME_KEY);
                packageName = intent.getStringExtra(Constants.PACKAGENAME_KEY);
                md5sum = intent.getStringExtra(Constants.MD5SUM_KEY);
                storeName = intent.getStringExtra(Constants.STORENAME_KEY);

                executeSpiceRequestWithMd5(md5sum, storeName);
            } else if (intent.getBooleanExtra(Constants.MARKET_INTENT, false)) {
                packageName = intent.getStringExtra(Constants.PACKAGENAME_KEY);

                executeSpiceRequestWithPackageName(packageName, null);
            }

            mCollapsingToolbarLayout.setTitle(appName);
        }

        private void executeSpiceRequestWithAppId(long appId, @Nullable String storeName, String packageName) {
            long cacheExpiryDuration = forceReload ? DurationInMillis.ALWAYS_EXPIRED : DurationInMillis.ONE_HOUR;
            spiceManager.execute(AptoideUtils.RepoUtils.buildGetAppRequestFromAppId(appId, storeName, packageName),
                    appId + bucketSize, cacheExpiryDuration, listener);
        }

        private void executeSpiceRequestWithMd5(String md5, String storeName) {
            long cacheExpiryDuration = forceReload ? DurationInMillis.ALWAYS_EXPIRED : DurationInMillis.ONE_HOUR;
            spiceManager.execute(AptoideUtils.RepoUtils.buildGetAppRequestFromMd5(md5, storeName), md5 + bucketSize,
                    cacheExpiryDuration, listener);
        }

        private void executeSpiceRequestWithPackageName(String packageName, String appName) {
            long cacheExpiryDuration = forceReload ? DurationInMillis.ALWAYS_EXPIRED : DurationInMillis.ONE_HOUR;
            spiceManager.execute(AptoideUtils.RepoUtils.buildGetAppRequestFromPackageName(packageName),
                    packageName + appName + bucketSize, cacheExpiryDuration, listener);
        }

        private void executeSpiceRequestWithAppRate(long appId, float rating) {
            mRatingBar.setIsIndicator(true);
            spiceManager.execute(AptoideUtils.RepoUtils.buildRateRequest(appId, rating),
                    new RequestListener<RateApp>() {
                        @Override
                        public void onRequestFailure(SpiceException spiceException) {
                            Toast.makeText(getActivity(), getString(R.string.error_occured), Toast.LENGTH_SHORT)
                                    .show();
                            mRatingBar.setIsIndicator(false);
                        }

                        @Override
                        public void onRequestSuccess(RateApp rateApp) {
                            mRatingBar.setIsIndicator(false);
                            Toast.makeText(getActivity(), getString(R.string.appview_rate_Success),
                                    Toast.LENGTH_SHORT).show();
                        }
                    });
        }

        class RatingBarClickListener implements RatingBar.OnRatingBarChangeListener {
            @Override
            public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
                if (!fromUser) {
                    return;
                }
                final Activity activity = getActivity();
                if (AptoideUtils.AccountUtils.isLoggedIn(activity)) {
                    executeSpiceRequestWithAppRate(appId, rating);
                } else {
                    Intent intent = new Intent(activity, MyAccountActivity.class);
                    activity.startActivity(intent);
                }
            }

        }

        public class DowngradeListener implements View.OnClickListener {

            private String icon;
            private String name;
            private String versionName;
            private String downgradeVersion;
            private String package_name;

            public DowngradeListener(String icon, String name, String versionName, String downgradeVersion,
                    String package_name) {
                this.icon = icon;
                this.name = name;
                this.versionName = versionName;
                this.downgradeVersion = downgradeVersion;
                this.package_name = package_name;
            }

            @Override
            public void onClick(View v) {
                reloadButtons = true;
                Fragment downgrade = new UninstallRetainFragment();
                Bundle args = new Bundle();
                args.putString("name", name);
                args.putString("package", package_name);
                args.putString("version", versionName);
                args.putString("downgradeVersion", downgradeVersion);
                args.putString("icon", icon);
                downgrade.setArguments(args);

                getFragmentManager().beginTransaction().add(downgrade, "downgrade").commit();
            }
        }

        public class InstallListener implements View.OnClickListener, DialogInterface.OnClickListener {

            protected String icon;
            protected String name;
            protected String versionName;
            protected String package_name;
            protected String md5;
            private long downloadId;
            private boolean paid;

            public InstallListener(String icon, String name, String versionName, String packageName, String md5,
                    boolean paid) {
                this.icon = icon;
                this.name = name;
                this.versionName = versionName;
                this.package_name = packageName;
                this.md5 = md5;
                this.paid = paid;
                this.downloadId = md5.hashCode();
            }

            protected Download makeDownLoad() {
                Download download = new Download();

                showRootDialog();

                download.setId(this.downloadId);
                download.setName(this.name);
                download.setVersion(this.versionName);
                download.setIcon(this.icon);
                download.setPackageName(this.package_name);
                download.setMd5(this.md5);
                download.setPaid(this.paid);
                if (!isUpdate)
                    download.setCpiUrl(getActivity().getIntent().getStringExtra("cpi"));
                return download;
            }

            @Override
            public void onClick(View v) {
                reloadButtons = true;
                if (appSuggested != null && appSuggested.getInfo().getCpc_url() != null) {
                    AptoideUtils.AdNetworks.knock(appSuggested.getInfo().getCpd_url());
                }

                if (cpd != null) {
                    AptoideUtils.AdNetworks.knock(cpd);
                }

                download();

                Analytics.ClickedOnInstallButton.clicked(package_name, developer);
            }

            @Override
            public void onClick(DialogInterface dialog, int which) {
                // shouldnt check if which is positive?
                download();
            }
        }
    }
}