package awais.instagrabber.fragments;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.Animatable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.util.Pair;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.view.GestureDetectorCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.LinearLayoutManager;

import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.controller.BaseControllerListener;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.imagepipeline.image.ImageInfo;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.LoadEventInfo;
import com.google.android.exoplayer2.source.MediaLoadData;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.source.dash.DashMediaSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import awais.instagrabber.BuildConfig;
import awais.instagrabber.R;
import awais.instagrabber.adapters.StoriesAdapter;
import awais.instagrabber.asyncs.CreateThreadAction;
import awais.instagrabber.asyncs.PostFetcher;
import awais.instagrabber.customviews.helpers.SwipeGestureListener;
import awais.instagrabber.databinding.FragmentStoryViewerBinding;
import awais.instagrabber.fragments.main.ProfileFragmentDirections;
import awais.instagrabber.interfaces.SwipeEvent;
import awais.instagrabber.models.FeedStoryModel;
import awais.instagrabber.models.HighlightModel;
import awais.instagrabber.models.StoryModel;
import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.models.stickers.PollModel;
import awais.instagrabber.models.stickers.QuestionModel;
import awais.instagrabber.models.stickers.QuizModel;
import awais.instagrabber.models.stickers.SliderModel;
import awais.instagrabber.models.stickers.SwipeUpModel;
import awais.instagrabber.repositories.requests.StoryViewerOptions;
import awais.instagrabber.repositories.requests.StoryViewerOptions.Type;
import awais.instagrabber.repositories.requests.directmessages.BroadcastOptions;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.StoryStickerResponse;
import awais.instagrabber.repositories.responses.directmessages.DirectThreadBroadcastResponse;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.DownloadUtils;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import awais.instagrabber.viewmodels.ArchivesViewModel;
import awais.instagrabber.viewmodels.FeedStoriesViewModel;
import awais.instagrabber.viewmodels.HighlightsViewModel;
import awais.instagrabber.viewmodels.StoriesViewModel;
import awais.instagrabber.webservices.DirectMessagesService;
import awais.instagrabber.webservices.MediaService;
import awais.instagrabber.webservices.ServiceCallback;
import awais.instagrabber.webservices.StoriesService;
//import awaisomereport.LogCollector;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

import static awais.instagrabber.customviews.helpers.SwipeGestureListener.SWIPE_THRESHOLD;
import static awais.instagrabber.customviews.helpers.SwipeGestureListener.SWIPE_VELOCITY_THRESHOLD;
import static awais.instagrabber.utils.Constants.MARK_AS_SEEN;
//import static awais.instagrabber.utils.Utils.logCollector;
import static awais.instagrabber.utils.Utils.settingsHelper;

public class StoryViewerFragment extends Fragment {
    private static final String TAG = "StoryViewerFragment";

    private AppCompatActivity fragmentActivity;
    private View root;
    private FragmentStoryViewerBinding binding;
    private String currentStoryUsername;
    private StoriesAdapter storiesAdapter;
    private SwipeEvent swipeEvent;
    private GestureDetectorCompat gestureDetector;
    private StoriesService storiesService;
    private MediaService mediaService;
    private StoryModel currentStory;
    private int slidePos;
    private int lastSlidePos;
    private String url;
    private PollModel poll;
    private QuestionModel question;
    private String[] mentions;
    private QuizModel quiz;
    private SliderModel slider;
    private MenuItem menuDownload, menuDm, menuProfile;
    private SimpleExoPlayer player;
    // private boolean isHashtag;
    // private boolean isLoc;
    // private String highlight;
    private String actionBarTitle, actionBarSubtitle;
    private boolean fetching = false, sticking = false, shouldRefresh = true;
    private boolean downloadVisible = false, dmVisible = false, profileVisible = true;
    private int currentFeedStoryIndex;
    private double sliderValue;
    private StoriesViewModel storiesViewModel;
    private ViewModel viewModel;
    // private boolean isHighlight;
    // private boolean isArchive;
    // private boolean isNotification;
    private DirectMessagesService directMessagesService;

    private final String cookie = settingsHelper.getString(Constants.COOKIE);
    private StoryViewerOptions options;

    @Override
    public void onCreate(@Nullable final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie);
        if (csrfToken == null) return;
        final long userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie);
        final String deviceId = settingsHelper.getString(Constants.DEVICE_UUID);
        fragmentActivity = (AppCompatActivity) requireActivity();
        storiesService = StoriesService.getInstance(csrfToken, userIdFromCookie, deviceId);
        mediaService = MediaService.getInstance(null, null, 0);
        directMessagesService = DirectMessagesService.getInstance(csrfToken, userIdFromCookie, deviceId);
        setHasOptionsMenu(true);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
        if (root != null) {
            shouldRefresh = false;
            return root;
        }
        binding = FragmentStoryViewerBinding.inflate(inflater, container, false);
        root = binding.getRoot();
        return root;
    }

    @Override
    public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
        if (!shouldRefresh) return;
        init();
        shouldRefresh = false;
    }

    @Override
    public void onCreateOptionsMenu(@NonNull final Menu menu, final MenuInflater menuInflater) {
        menuInflater.inflate(R.menu.story_menu, menu);
        menuDownload = menu.findItem(R.id.action_download);
        menuDm = menu.findItem(R.id.action_dms);
        menuProfile = menu.findItem(R.id.action_profile);
        menuDownload.setVisible(downloadVisible);
        menuDm.setVisible(dmVisible);
        menuProfile.setVisible(profileVisible);
    }

    @Override
    public void onPrepareOptionsMenu(@NonNull final Menu menu) {
        // hide menu items from activity
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
        final Context context = getContext();
        if (context == null) return false;
        int itemId = item.getItemId();
        if (itemId == R.id.action_download) {
            if (ContextCompat.checkSelfPermission(context, DownloadUtils.PERMS[0]) == PackageManager.PERMISSION_GRANTED)
                downloadStory();
            else
                ActivityCompat.requestPermissions(requireActivity(), DownloadUtils.PERMS, 8020);
            return true;
        }
        if (itemId == R.id.action_dms) {
            final EditText input = new EditText(context);
            input.setHint(R.string.reply_hint);
            new AlertDialog.Builder(context)
                    .setTitle(R.string.reply_story)
                    .setView(input)
                    .setPositiveButton(R.string.confirm, (d, w) -> new CreateThreadAction(cookie, currentStory.getUserId(), thread -> {
                        if (thread == null) {
                            Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
                            return;
                        }
                        try {
                            final Call<DirectThreadBroadcastResponse> request = directMessagesService
                                    .broadcastStoryReply(BroadcastOptions.ThreadIdOrUserIds.of(thread.getThreadId()),
                                                         input.getText().toString(),
                                                         currentStory.getStoryMediaId(),
                                                         String.valueOf(currentStory.getUserId()));
                            request.enqueue(new Callback<DirectThreadBroadcastResponse>() {
                                @Override
                                public void onResponse(@NonNull final Call<DirectThreadBroadcastResponse> call,
                                                       @NonNull final Response<DirectThreadBroadcastResponse> response) {
                                    if (!response.isSuccessful()) {
                                        Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
                                        return;
                                    }
                                    Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show();
                                }

                                @Override
                                public void onFailure(@NonNull final Call<DirectThreadBroadcastResponse> call, @NonNull final Throwable t) {
                                    try {
                                        Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
                                        Log.e(TAG, "onFailure: ", t);
                                    } catch (Throwable ignored) {}
                                }
                            });
                        } catch (UnsupportedEncodingException e) {
                            Log.e(TAG, "Error", e);
                        }
                    }).execute())
                    .setNegativeButton(R.string.cancel, null)
                    .show();
            return true;
        }
        if (itemId == R.id.action_profile) {
            openProfile("@" + currentStory.getUsername());
        }
        return false;
    }

    @Override
    public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 8020 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            downloadStory();
    }

    @Override
    public void onPause() {
        super.onPause();
        releasePlayer();
    }

    @Override
    public void onResume() {
        super.onResume();
        final ActionBar actionBar = fragmentActivity.getSupportActionBar();
        if (actionBar != null) {
            actionBar.setTitle(actionBarTitle);
            actionBar.setSubtitle(actionBarSubtitle);
        }
        setHasOptionsMenu(true);
    }

    @Override
    public void onDestroy() {
        releasePlayer();
        // reset subtitle
        final ActionBar actionBar = fragmentActivity.getSupportActionBar();
        if (actionBar != null) {
            actionBar.setSubtitle(null);
        }
        super.onDestroy();
    }

    private void init() {
        if (getArguments() == null) return;
        final StoryViewerFragmentArgs fragmentArgs = StoryViewerFragmentArgs.fromBundle(getArguments());
        options = fragmentArgs.getOptions();
        currentFeedStoryIndex = options.getCurrentFeedStoryIndex();
        // highlight = fragmentArgs.getHighlight();
        // isHighlight = !TextUtils.isEmpty(highlight);
        // isArchive = fragmentArgs.getIsArchive();
        // isNotification = fragmentArgs.getIsNotification();
        final Type type = options.getType();
        if (currentFeedStoryIndex >= 0) {
            switch (type) {
                case HIGHLIGHT:
                    viewModel = new ViewModelProvider(fragmentActivity).get(HighlightsViewModel.class);
                    break;
                case STORY_ARCHIVE:
                    viewModel = new ViewModelProvider(fragmentActivity).get(ArchivesViewModel.class);
                    break;
                default:
                case FEED_STORY_POSITION:
                    viewModel = new ViewModelProvider(fragmentActivity).get(FeedStoriesViewModel.class);
                    break;
            }
        }
        setupStories();
    }

    private void setupStories() {
        storiesViewModel = new ViewModelProvider(this).get(StoriesViewModel.class);
        setupListeners();
        final Context context = getContext();
        if (context == null) return;
        binding.storiesList.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
        storiesAdapter = new StoriesAdapter((model, position) -> {
            currentStory = model;
            slidePos = position;
            refreshStory();
        });
        binding.storiesList.setAdapter(storiesAdapter);
        storiesViewModel.getList().observe(fragmentActivity, storiesAdapter::submitList);
        resetView();
    }

    @SuppressLint("ClickableViewAccessibility")
    private void setupListeners() {
        final boolean hasFeedStories;
        List<?> models = null;
        if (currentFeedStoryIndex >= 0) {
            final Type type = options.getType();
            switch (type) {
                case HIGHLIGHT:
                    final HighlightsViewModel highlightsViewModel = (HighlightsViewModel) viewModel;
                    models = highlightsViewModel.getList().getValue();
                    break;
                case FEED_STORY_POSITION:
                    final FeedStoriesViewModel feedStoriesViewModel = (FeedStoriesViewModel) viewModel;
                    models = feedStoriesViewModel.getList().getValue();
                    break;
                case STORY_ARCHIVE:
                    final ArchivesViewModel archivesViewModel = (ArchivesViewModel) viewModel;
                    models = archivesViewModel.getList().getValue();
                    break;
            }
        }
        hasFeedStories = models != null && !models.isEmpty();
        final List<?> finalModels = models;
        final Context context = getContext();
        if (context == null) return;
        swipeEvent = isRightSwipe -> {
            final List<StoryModel> storyModels = storiesViewModel.getList().getValue();
            final int storiesLen = storyModels == null ? 0 : storyModels.size();
            if (sticking) {
                Toast.makeText(context, R.string.follower_wait_to_load, Toast.LENGTH_SHORT).show();
                return;
            }
            if (storiesLen <= 0) return;
            final boolean isLeftSwipe = !isRightSwipe;
            final boolean endOfCurrentStories = slidePos + 1 >= storiesLen;
            final boolean swipingBeyondCurrentStories = (endOfCurrentStories && isLeftSwipe) || (slidePos == 0 && isRightSwipe);
            if (swipingBeyondCurrentStories && hasFeedStories) {
                final int index = currentFeedStoryIndex;
                if ((isRightSwipe && index == 0) || (isLeftSwipe && index == finalModels.size() - 1)) {
                    Toast.makeText(context, R.string.no_more_stories, Toast.LENGTH_SHORT).show();
                    return;
                }
                final Object feedStoryModel = isRightSwipe
                                              ? finalModels.get(index - 1)
                                              : finalModels.size() == index + 1 ? null : finalModels.get(index + 1);
                paginateStories(feedStoryModel, finalModels.get(index), context, isRightSwipe, currentFeedStoryIndex == finalModels.size() - 2);
                return;
            }
            if (isRightSwipe) {
                if (--slidePos <= 0) {
                    slidePos = 0;
                }
            } else if (++slidePos >= storiesLen) {
                slidePos = storiesLen - 1;
            }
            currentStory = storyModels.get(slidePos);
            refreshStory();
        };
        gestureDetector = new GestureDetectorCompat(context, new SwipeGestureListener(swipeEvent));
        binding.playerView.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event));
        final GestureDetector.SimpleOnGestureListener simpleOnGestureListener = new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX, final float velocityY) {
                final float diffX = e2.getX() - e1.getX();
                try {
                    if (Math.abs(diffX) > Math.abs(e2.getY() - e1.getY()) && Math.abs(diffX) > SWIPE_THRESHOLD
                            && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        swipeEvent.onSwipe(diffX > 0);
                        return true;
                    }
                } catch (final Exception e) {
//                    if (logCollector != null)
//                        logCollector.appendException(e, LogCollector.LogFile.ACTIVITY_STORY_VIEWER, "setupListeners",
//                                                     new Pair<>("swipeEvent", swipeEvent),
//                                                     new Pair<>("diffX", diffX));
                    if (BuildConfig.DEBUG) Log.e(TAG, "Error", e);
                }
                return false;
            }
        };

        if (hasFeedStories) {
            binding.btnBackward.setVisibility(currentFeedStoryIndex == 0 ? View.INVISIBLE : View.VISIBLE);
            binding.btnForward.setVisibility(currentFeedStoryIndex == finalModels.size() - 1 ? View.INVISIBLE : View.VISIBLE);
            binding.btnBackward.setOnClickListener(v -> paginateStories(finalModels.get(currentFeedStoryIndex - 1),
                                                                        finalModels.get(currentFeedStoryIndex),
                                                                        context, true, false));
            binding.btnForward.setOnClickListener(v -> paginateStories(finalModels.get(currentFeedStoryIndex + 1),
                                                                       finalModels.get(currentFeedStoryIndex),
                                                                       context, false,
                                                                       currentFeedStoryIndex == finalModels.size() - 2));
        }

        binding.imageViewer.setTapListener(simpleOnGestureListener);
        binding.spotify.setOnClickListener(v -> {
            final Object tag = v.getTag();
            if (tag instanceof CharSequence) {
                Utils.openURL(context, tag.toString());
            }
        });
        binding.swipeUp.setOnClickListener(v -> {
            final Object tag = v.getTag();
            if (tag instanceof CharSequence) {
                Utils.openURL(context, tag.toString());
            }
        });
        binding.viewStoryPost.setOnClickListener(v -> {
            final Object tag = v.getTag();
            if (!(tag instanceof CharSequence)) return;
            final String mediaId = tag.toString();
            final AlertDialog alertDialog = new AlertDialog.Builder(context)
                    .setCancelable(false)
                    .setView(R.layout.dialog_opening_post)
                    .create();
            alertDialog.show();
            mediaService.fetch(Long.valueOf(mediaId), new ServiceCallback<Media>() {
                @Override
                public void onSuccess(final Media feedModel) {
                    final PostViewV2Fragment fragment = PostViewV2Fragment
                            .builder(feedModel)
                            .build();
                    fragment.setOnShowListener(dialog -> alertDialog.dismiss());
                    fragment.show(getChildFragmentManager(), "post_view");
                }

                @Override
                public void onFailure(final Throwable t) {
                    alertDialog.dismiss();
                    Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
                }
            });
        });
        final View.OnClickListener storyActionListener = v -> {
            final Object tag = v.getTag();
            if (tag instanceof PollModel) {
                poll = (PollModel) tag;
                if (poll.getMyChoice() > -1) {
                    new AlertDialog.Builder(context).setTitle(R.string.voted_story_poll)
                                                    .setAdapter(new ArrayAdapter<>(context, android.R.layout.simple_list_item_1,
                                                                                   new String[]{
                                                                                           (poll.getMyChoice() == 0 ? "√ " : "") + poll
                                                                                                   .getLeftChoice() + " (" + poll
                                                                                                   .getLeftCount() + ")",
                                                                                           (poll.getMyChoice() == 1 ? "√ " : "") + poll
                                                                                                   .getRightChoice() + " (" + poll
                                                                                                   .getRightCount() + ")"
                                                                                   }), null)
                                                    .setPositiveButton(R.string.ok, null)
                                                    .show();
                } else {
                    new AlertDialog.Builder(context)
                            .setTitle(poll.getQuestion())
                            .setAdapter(new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, new String[]{
                                    poll.getLeftChoice() + " (" + poll.getLeftCount() + ")",
                                    poll.getRightChoice() + " (" + poll.getRightCount() + ")"
                            }), (d, w) -> {
                                sticking = true;
                                storiesService.respondToPoll(
                                        currentStory.getStoryMediaId().split("_")[0],
                                        poll.getId(),
                                        w,
                                        new ServiceCallback<StoryStickerResponse>() {
                                            @Override
                                            public void onSuccess(final StoryStickerResponse result) {
                                                sticking = false;
                                                try {
                                                    poll.setMyChoice(w);
                                                    Toast.makeText(context, R.string.votef_story_poll, Toast.LENGTH_SHORT).show();
                                                } catch (Exception ignored) {}
                                            }

                                            @Override
                                            public void onFailure(final Throwable t) {
                                                sticking = false;
                                                Log.e(TAG, "Error responding", t);
                                                try {
                                                    Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
                                                } catch (Exception ignored) {}
                                            }
                                        });
                            })
                            .setPositiveButton(R.string.cancel, null)
                            .show();
                }
            } else if (tag instanceof QuestionModel) {
                question = (QuestionModel) tag;
                final EditText input = new EditText(context);
                input.setHint(R.string.answer_hint);
                new AlertDialog.Builder(context)
                        .setTitle(question.getQuestion())
                        .setView(input)
                        .setPositiveButton(R.string.confirm, (d, w) -> {
                            sticking = true;
                            storiesService.respondToQuestion(
                                    currentStory.getStoryMediaId().split("_")[0],
                                    question.getId(),
                                    input.getText().toString(),
                                    new ServiceCallback<StoryStickerResponse>() {
                                        @Override
                                        public void onSuccess(final StoryStickerResponse result) {
                                            sticking = false;
                                            try {
                                                Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show();
                                            } catch (Exception ignored) {}
                                        }

                                        @Override
                                        public void onFailure(final Throwable t) {
                                            sticking = false;
                                            Log.e(TAG, "Error responding", t);
                                            try {
                                                Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
                                            } catch (Exception ignored) {}
                                        }
                                    });
                        })
                        .setNegativeButton(R.string.cancel, null)
                        .show();
            } else if (tag instanceof String[]) {
                mentions = (String[]) tag;
                new AlertDialog.Builder(context)
                        .setTitle(R.string.story_mentions)
                        .setAdapter(new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, mentions), (d, w) -> openProfile(mentions[w]))
                        .setPositiveButton(R.string.cancel, null)
                        .show();
            } else if (tag instanceof QuizModel) {
                String[] choices = new String[quiz.getChoices().length];
                for (int q = 0; q < choices.length; ++q) {
                    choices[q] = (quiz.getMyChoice() == q ? "√ " : "") + quiz.getChoices()[q] + " (" + quiz.getCounts()[q] + ")";
                }
                new AlertDialog.Builder(context)
                        .setTitle(quiz.getMyChoice() > -1 ? getString(R.string.story_quizzed) : quiz.getQuestion())
                        .setAdapter(new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, choices), (d, w) -> {
                            if (quiz.getMyChoice() == -1) {
                                sticking = true;
                                storiesService.respondToQuiz(
                                        currentStory.getStoryMediaId().split("_")[0],
                                        quiz.getId(),
                                        w,
                                        new ServiceCallback<StoryStickerResponse>() {
                                            @Override
                                            public void onSuccess(final StoryStickerResponse result) {
                                                sticking = false;
                                                try {
                                                    quiz.setMyChoice(w);
                                                    Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show();
                                                } catch (Exception ignored) {}
                                            }

                                            @Override
                                            public void onFailure(final Throwable t) {
                                                sticking = false;
                                                Log.e(TAG, "Error responding", t);
                                                try {
                                                    Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
                                                } catch (Exception ignored) {}
                                            }
                                        });
                            }
                        })
                        .setPositiveButton(R.string.cancel, null)
                        .show();
            } else if (tag instanceof SliderModel) {
                slider = (SliderModel) tag;
                NumberFormat percentage = NumberFormat.getPercentInstance();
                percentage.setMaximumFractionDigits(2);
                LinearLayout sliderView = new LinearLayout(context);
                sliderView.setLayoutParams(new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.WRAP_CONTENT));
                sliderView.setOrientation(LinearLayout.VERTICAL);
                TextView tv = new TextView(context);
                tv.setGravity(Gravity.CENTER_HORIZONTAL);
                final SeekBar input = new SeekBar(context);
                double avg = slider.getAverage() * 100;
                input.setProgress((int) avg);
                sliderView.addView(input);
                sliderView.addView(tv);
                if (slider.getMyChoice().isNaN() && slider.canVote()) {
                    input.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                        @Override
                        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                            sliderValue = progress / 100.0;
                            tv.setText(percentage.format(sliderValue));
                        }

                        @Override
                        public void onStartTrackingTouch(SeekBar seekBar) {
                        }

                        @Override
                        public void onStopTrackingTouch(SeekBar seekBar) {
                        }
                    });
                    new AlertDialog.Builder(context)
                            .setTitle(TextUtils.isEmpty(slider.getQuestion()) ? slider.getEmoji() : slider.getQuestion())
                            .setMessage(getResources().getQuantityString(R.plurals.slider_info,
                                                                         slider.getVoteCount(),
                                                                         slider.getVoteCount(),
                                                                         percentage.format(slider.getAverage())))
                            .setView(sliderView)
                            .setPositiveButton(R.string.confirm, (d, w) -> {
                                sticking = true;
                                storiesService.respondToSlider(
                                        currentStory.getStoryMediaId().split("_")[0],
                                        slider.getId(),
                                        sliderValue,
                                        new ServiceCallback<StoryStickerResponse>() {
                                            @Override
                                            public void onSuccess(final StoryStickerResponse result) {
                                                sticking = false;
                                                try {
                                                    slider.setMyChoice(sliderValue);
                                                    Toast.makeText(context, R.string.answered_story, Toast.LENGTH_SHORT).show();
                                                } catch (Exception ignored) {}
                                            }

                                            @Override
                                            public void onFailure(final Throwable t) {
                                                sticking = false;
                                                Log.e(TAG, "Error responding", t);
                                                try {
                                                    Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
                                                } catch (Exception ignored) {}
                                            }
                                        });
                            })
                            .setNegativeButton(R.string.cancel, null)
                            .show();
                } else {
                    input.setEnabled(false);
                    tv.setText(getString(R.string.slider_answer, percentage.format(slider.getMyChoice())));
                    new AlertDialog.Builder(context)
                            .setTitle(TextUtils.isEmpty(slider.getQuestion()) ? slider.getEmoji() : slider.getQuestion())
                            .setMessage(getResources().getQuantityString(R.plurals.slider_info,
                                                                         slider.getVoteCount(),
                                                                         slider.getVoteCount(),
                                                                         percentage.format(slider.getAverage())))
                            .setView(sliderView)
                            .setPositiveButton(R.string.ok, null)
                            .show();
                }
            }
        };
        binding.poll.setOnClickListener(storyActionListener);
        binding.answer.setOnClickListener(storyActionListener);
        binding.mention.setOnClickListener(storyActionListener);
        binding.quiz.setOnClickListener(storyActionListener);
        binding.slider.setOnClickListener(storyActionListener);
    }

    private void resetView() {
        final Context context = getContext();
        if (context == null) return;
        StoryModel live = null;
        slidePos = 0;
        lastSlidePos = 0;
        if (menuDownload != null) menuDownload.setVisible(false);
        if (menuDm != null) menuDm.setVisible(false);
        if (menuProfile != null) menuProfile.setVisible(false);
        downloadVisible = false;
        dmVisible = false;
        profileVisible = false;
        binding.imageViewer.setController(null);
        releasePlayer();
        String currentStoryMediaId = null;
        final Type type = options.getType();
        StoryViewerOptions fetchOptions = null;
        switch (type) {
            case HIGHLIGHT: {
                final HighlightsViewModel highlightsViewModel = (HighlightsViewModel) viewModel;
                final List<HighlightModel> models = highlightsViewModel.getList().getValue();
                if (models == null || models.isEmpty() || currentFeedStoryIndex >= models.size() || currentFeedStoryIndex < 0) {
                    Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
                    return;
                }
                final HighlightModel model = models.get(currentFeedStoryIndex);
                currentStoryMediaId = model.getId();
                fetchOptions = StoryViewerOptions.forHighlight(model.getId());
                currentStoryUsername = model.getTitle();
                break;
            }
            case FEED_STORY_POSITION: {
                final FeedStoriesViewModel feedStoriesViewModel = (FeedStoriesViewModel) viewModel;
                final List<FeedStoryModel> models = feedStoriesViewModel.getList().getValue();
                if (models == null || currentFeedStoryIndex >= models.size() || currentFeedStoryIndex < 0) return;
                final FeedStoryModel model = models.get(currentFeedStoryIndex);
                currentStoryMediaId = model.getStoryMediaId();
                currentStoryUsername = model.getProfileModel().getUsername();
                fetchOptions = StoryViewerOptions.forUser(Long.parseLong(currentStoryMediaId), currentStoryUsername);
                if (model.isLive()) {
                    live = model.getFirstStoryModel();
                }
                break;
            }
            case STORY_ARCHIVE: {
                final ArchivesViewModel archivesViewModel = (ArchivesViewModel) viewModel;
                final List<HighlightModel> models = archivesViewModel.getList().getValue();
                if (models == null || models.isEmpty() || currentFeedStoryIndex >= models.size() || currentFeedStoryIndex < 0) {
                    Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
                    return;
                }
                final HighlightModel model = models.get(currentFeedStoryIndex);
                currentStoryMediaId = parseStoryMediaId(model.getId());
                currentStoryUsername = model.getTitle();
                fetchOptions = StoryViewerOptions.forStoryArchive(model.getId());
                break;
            }
        }
        if (type == Type.USER) {
            currentStoryMediaId = String.valueOf(options.getId());
            currentStoryUsername = options.getName();
            fetchOptions = StoryViewerOptions.forUser(options.getId(), currentStoryUsername);
        }
        setTitle(type);
        storiesViewModel.getList().setValue(Collections.emptyList());
        if (type == Type.STORY) {
            storiesService.fetch(options.getId(), new ServiceCallback<StoryModel>() {
                @Override
                public void onSuccess(final StoryModel storyModel) {
                    fetching = false;
                    binding.storiesList.setVisibility(View.GONE);
                    if (storyModel == null) {
                        storiesViewModel.getList().setValue(Collections.emptyList());
                        currentStory = null;
                        return;
                    }
                    storiesViewModel.getList().setValue(Collections.singletonList(storyModel));
                    currentStory = storyModel;
                    refreshStory();
                }

                @Override
                public void onFailure(final Throwable t) {
                    Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
                    Log.e(TAG, "Error", t);
                }
            });
            return;
        }
        if (currentStoryMediaId == null) return;
        final ServiceCallback<List<StoryModel>> storyCallback = new ServiceCallback<List<StoryModel>>() {
            @Override
            public void onSuccess(final List<StoryModel> storyModels) {
                fetching = false;
                if (storyModels == null || storyModels.isEmpty()) {
                    storiesViewModel.getList().setValue(Collections.emptyList());
                    currentStory = null;
                    binding.storiesList.setVisibility(View.GONE);
                    return;
                }
                binding.storiesList.setVisibility((storyModels.size() == 1 && currentFeedStoryIndex == -1) ? View.GONE : View.VISIBLE);
                if (currentFeedStoryIndex == -1) {
                    binding.btnBackward.setVisibility(View.GONE);
                    binding.btnForward.setVisibility(View.GONE);
                }
                storiesViewModel.getList().setValue(storyModels);
                currentStory = storyModels.get(0);
                refreshStory();
            }

            @Override
            public void onFailure(final Throwable t) {
                Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
                Log.e(TAG, "Error", t);
            }
        };
        if (live != null) {
            storyCallback.onSuccess(Collections.singletonList(live));
            return;
        }
        storiesService.getUserStory(fetchOptions, storyCallback);
    }

    private void setTitle(final Type type) {
        final boolean hasUsername = !TextUtils.isEmpty(currentStoryUsername);
        if (type == Type.HIGHLIGHT) {
            final ActionBar actionBar = fragmentActivity.getSupportActionBar();
            if (actionBar != null) {
                actionBarTitle = options.getName();
                actionBar.setTitle(options.getName());
            }
        } else if (hasUsername) {
            currentStoryUsername = currentStoryUsername.replace("@", "");
            final ActionBar actionBar = fragmentActivity.getSupportActionBar();
            if (actionBar != null) {
                actionBarTitle = currentStoryUsername;
                actionBar.setTitle(currentStoryUsername);
            }
        }
    }

    private void refreshStory() {
        if (binding.storiesList.getVisibility() == View.VISIBLE) {
            final List<StoryModel> storyModels = storiesViewModel.getList().getValue();
            if (storyModels != null && storyModels.size() > 0) {
                StoryModel item = storyModels.get(lastSlidePos);
                if (item != null) {
                    item.setCurrentSlide(false);
                    storiesAdapter.notifyItemChanged(lastSlidePos, item);
                }
                item = storyModels.get(slidePos);
                if (item != null) {
                    item.setCurrentSlide(true);
                    storiesAdapter.notifyItemChanged(slidePos, item);
                }
            }
        }
        lastSlidePos = slidePos;

        final MediaItemType itemType = currentStory.getItemType();

        url = itemType == MediaItemType.MEDIA_TYPE_IMAGE ? currentStory.getStoryUrl() : currentStory.getVideoUrl();

        if (itemType != MediaItemType.MEDIA_TYPE_LIVE) {
            final String shortCode = currentStory.getTappableShortCode();
            binding.viewStoryPost.setVisibility(shortCode != null ? View.VISIBLE : View.GONE);
            binding.viewStoryPost.setTag(shortCode);

            final String spotify = currentStory.getSpotify();
            binding.spotify.setVisibility(spotify != null ? View.VISIBLE : View.GONE);
            binding.spotify.setTag(spotify);

            poll = currentStory.getPoll();
            binding.poll.setVisibility(poll != null ? View.VISIBLE : View.GONE);
            binding.poll.setTag(poll);

            question = currentStory.getQuestion();
            binding.answer.setVisibility((question != null) ? View.VISIBLE : View.GONE);
            binding.answer.setTag(question);

            mentions = currentStory.getMentions();
            binding.mention.setVisibility((mentions != null && mentions.length > 0) ? View.VISIBLE : View.GONE);
            binding.mention.setTag(mentions);

            quiz = currentStory.getQuiz();
            binding.quiz.setVisibility(quiz != null ? View.VISIBLE : View.GONE);
            binding.quiz.setTag(quiz);

            slider = currentStory.getSlider();
            binding.slider.setVisibility(slider != null ? View.VISIBLE : View.GONE);
            binding.slider.setTag(slider);

            final SwipeUpModel swipeUp = currentStory.getSwipeUp();
            if (swipeUp != null) {
                binding.swipeUp.setVisibility(View.VISIBLE);
                binding.swipeUp.setText(swipeUp.getText());
                binding.swipeUp.setTag(swipeUp.getUrl());
            } else binding.swipeUp.setVisibility(View.GONE);
        }

        releasePlayer();
        final Type type = options.getType();
        if (type == Type.HASHTAG || type == Type.LOCATION) {
            final ActionBar actionBar = fragmentActivity.getSupportActionBar();
            if (actionBar != null) {
                actionBarTitle = currentStory.getUsername();
                actionBar.setTitle(currentStory.getUsername());
            }
        }
        if (itemType == MediaItemType.MEDIA_TYPE_VIDEO) setupVideo();
        else if (itemType == MediaItemType.MEDIA_TYPE_LIVE) setupLive();
        else setupImage();

        final ActionBar actionBar = fragmentActivity.getSupportActionBar();
        actionBarSubtitle = Utils.datetimeParser.format(new Date(currentStory.getTimestamp() * 1000L));
        if (actionBar != null) {
            try {
                actionBar.setSubtitle(actionBarSubtitle);
            } catch (Exception e) {
                Log.e(TAG, "refreshStory: ", e);
            }
        }

        if (settingsHelper.getBoolean(MARK_AS_SEEN))
            storiesService.seen(currentStory.getStoryMediaId(),
                                currentStory.getTimestamp(),
                                System.currentTimeMillis() / 1000,
                                null);
    }

    private void downloadStory() {
        final Context context = getContext();
        if (context == null) return;
        if (currentStory == null) {
            Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
            return;
        }
        DownloadUtils.download(context, currentStory);
    }

    private void setupImage() {
        binding.progressView.setVisibility(View.VISIBLE);
        binding.playerView.setVisibility(View.GONE);
        binding.imageViewer.setVisibility(View.VISIBLE);
        final ImageRequest requestBuilder = ImageRequestBuilder.newBuilderWithSource(Uri.parse(url))
                                                               .setLocalThumbnailPreviewsEnabled(true)
                                                               .setProgressiveRenderingEnabled(true)
                                                               .build();
        final DraweeController controller = Fresco.newDraweeControllerBuilder()
                                                  .setImageRequest(requestBuilder)
                                                  .setOldController(binding.imageViewer.getController())
                                                  .setControllerListener(new BaseControllerListener<ImageInfo>() {

                                                      @Override
                                                      public void onFailure(final String id, final Throwable throwable) {
                                                          binding.progressView.setVisibility(View.GONE);
                                                      }

                                                      @Override
                                                      public void onFinalImageSet(final String id,
                                                                                  final ImageInfo imageInfo,
                                                                                  final Animatable animatable) {
                                                          if (menuDownload != null) {
                                                              downloadVisible = true;
                                                              menuDownload.setVisible(true);
                                                          }
                                                          if (currentStory.canReply() && menuDm != null) {
                                                              dmVisible = true;
                                                              menuDm.setVisible(true);
                                                          }
                                                          if (!TextUtils.isEmpty(currentStory.getUsername())) {
                                                              profileVisible = true;
                                                              menuProfile.setVisible(true);
                                                          }
                                                          binding.progressView.setVisibility(View.GONE);
                                                      }
                                                  })
                                                  .build();
        binding.imageViewer.setController(controller);
    }

    private void setupVideo() {
        binding.playerView.setVisibility(View.VISIBLE);
        binding.progressView.setVisibility(View.GONE);
        binding.imageViewer.setVisibility(View.GONE);
        binding.imageViewer.setController(null);

        final Context context = getContext();
        if (context == null) return;
        player = new SimpleExoPlayer.Builder(context).build();
        binding.playerView.setPlayer(player);
        player.setPlayWhenReady(settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS));

        final Uri uri = Uri.parse(url);
        final MediaItem mediaItem = MediaItem.fromUri(uri);
        final ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(new DefaultDataSourceFactory(context, "instagram"))
                .createMediaSource(mediaItem);
        mediaSource.addEventListener(new Handler(), new MediaSourceEventListener() {
            @Override
            public void onLoadCompleted(final int windowIndex,
                                        @Nullable final MediaSource.MediaPeriodId mediaPeriodId,
                                        @NonNull final LoadEventInfo loadEventInfo,
                                        @NonNull final MediaLoadData mediaLoadData) {
                if (menuDownload != null) {
                    downloadVisible = true;
                    menuDownload.setVisible(true);
                }
                if (currentStory.canReply() && menuDm != null) {
                    dmVisible = true;
                    menuDm.setVisible(true);
                }
                if (!TextUtils.isEmpty(currentStory.getUsername()) && menuProfile != null) {
                    profileVisible = true;
                    menuProfile.setVisible(true);
                }
                binding.progressView.setVisibility(View.GONE);
            }

            @Override
            public void onLoadStarted(final int windowIndex,
                                      @Nullable final MediaSource.MediaPeriodId mediaPeriodId,
                                      @NonNull final LoadEventInfo loadEventInfo,
                                      @NonNull final MediaLoadData mediaLoadData) {
                if (menuDownload != null) {
                    downloadVisible = true;
                    menuDownload.setVisible(true);
                }
                if (currentStory.canReply() && menuDm != null) {
                    dmVisible = true;
                    menuDm.setVisible(true);
                }
                if (!TextUtils.isEmpty(currentStory.getUsername()) && menuProfile != null) {
                    profileVisible = true;
                    menuProfile.setVisible(true);
                }
                binding.progressView.setVisibility(View.VISIBLE);
            }

            @Override
            public void onLoadCanceled(final int windowIndex,
                                       @Nullable final MediaSource.MediaPeriodId mediaPeriodId,
                                       @NonNull final LoadEventInfo loadEventInfo,
                                       @NonNull final MediaLoadData mediaLoadData) {
                binding.progressView.setVisibility(View.GONE);
            }

            @Override
            public void onLoadError(final int windowIndex,
                                    @Nullable final MediaSource.MediaPeriodId mediaPeriodId,
                                    @NonNull final LoadEventInfo loadEventInfo,
                                    @NonNull final MediaLoadData mediaLoadData,
                                    @NonNull final IOException error,
                                    final boolean wasCanceled) {
                if (menuDownload != null) {
                    downloadVisible = false;
                    menuDownload.setVisible(false);
                }
                if (menuDm != null) {
                    dmVisible = false;
                    menuDm.setVisible(false);
                }
                if (menuProfile != null) {
                    profileVisible = false;
                    menuProfile.setVisible(false);
                }
                binding.progressView.setVisibility(View.GONE);
            }
        });
        player.setMediaSource(mediaSource);
        player.prepare();

        binding.playerView.setOnClickListener(v -> {
            if (player != null) {
                if (player.getPlaybackState() == Player.STATE_ENDED) player.seekTo(0);
                player.setPlayWhenReady(player.getPlaybackState() == Player.STATE_ENDED || !player.isPlaying());
            }
        });
    }

    private void setupLive() {
        binding.playerView.setVisibility(View.VISIBLE);
        binding.progressView.setVisibility(View.GONE);
        binding.imageViewer.setVisibility(View.GONE);
        binding.imageViewer.setController(null);

        if (menuDownload != null) menuDownload.setVisible(false);
        if (menuDm != null) menuDm.setVisible(false);

        final Context context = getContext();
        if (context == null) return;
        player = new SimpleExoPlayer.Builder(context).build();
        binding.playerView.setPlayer(player);
        player.setPlayWhenReady(settingsHelper.getBoolean(Constants.AUTOPLAY_VIDEOS));

        final Uri uri = Uri.parse(url);
        final MediaItem mediaItem = MediaItem.fromUri(uri);
        final DashMediaSource mediaSource = new DashMediaSource.Factory(new DefaultDataSourceFactory(context, "instagram"))
                .createMediaSource(mediaItem);
        mediaSource.addEventListener(new Handler(), new MediaSourceEventListener() {
            @Override
            public void onLoadCompleted(final int windowIndex,
                                        @Nullable final MediaSource.MediaPeriodId mediaPeriodId,
                                        @NonNull final LoadEventInfo loadEventInfo,
                                        @NonNull final MediaLoadData mediaLoadData) {
                binding.progressView.setVisibility(View.GONE);
            }

            @Override
            public void onLoadStarted(final int windowIndex,
                                      @Nullable final MediaSource.MediaPeriodId mediaPeriodId,
                                      @NonNull final LoadEventInfo loadEventInfo,
                                      @NonNull final MediaLoadData mediaLoadData) {
                binding.progressView.setVisibility(View.VISIBLE);
            }

            @Override
            public void onLoadCanceled(final int windowIndex,
                                       @Nullable final MediaSource.MediaPeriodId mediaPeriodId,
                                       @NonNull final LoadEventInfo loadEventInfo,
                                       @NonNull final MediaLoadData mediaLoadData) {
                binding.progressView.setVisibility(View.GONE);
            }

            @Override
            public void onLoadError(final int windowIndex,
                                    @Nullable final MediaSource.MediaPeriodId mediaPeriodId,
                                    @NonNull final LoadEventInfo loadEventInfo,
                                    @NonNull final MediaLoadData mediaLoadData,
                                    @NonNull final IOException error,
                                    final boolean wasCanceled) {
                binding.progressView.setVisibility(View.GONE);
            }
        });
        player.setMediaSource(mediaSource);
        player.prepare();

        binding.playerView.setOnClickListener(v -> {
            if (player != null) {
                if (player.getPlaybackState() == Player.STATE_ENDED) player.seekTo(0);
                player.setPlayWhenReady(player.getPlaybackState() == Player.STATE_ENDED || !player.isPlaying());
            }
        });
    }


    private void openProfile(final String username) {
        final ActionBar actionBar = fragmentActivity.getSupportActionBar();
        if (actionBar != null) {
            actionBar.setSubtitle(null);
        }
        final char t = username.charAt(0);
        if (t == '@') {
            final NavDirections action = HashTagFragmentDirections.actionGlobalProfileFragment(username);
            NavHostFragment.findNavController(this).navigate(action);
        } else if (t == '#') {
            final NavDirections action = HashTagFragmentDirections.actionGlobalHashTagFragment(username.substring(1));
            NavHostFragment.findNavController(this).navigate(action);
        } else {
            final NavDirections action = ProfileFragmentDirections
                    .actionGlobalLocationFragment(Long.parseLong(username.split(" \\(")[1].replace(")", "")));
            NavHostFragment.findNavController(this).navigate(action);
        }
    }

    private void releasePlayer() {
        if (player == null) return;
        try { player.stop(true); } catch (Exception ignored) { }
        try { player.release(); } catch (Exception ignored) { }
        player = null;
    }

    private void paginateStories(Object newFeedStory, Object oldFeedStory, Context context, boolean backward, boolean last) {
        if (newFeedStory != null) {
            if (fetching) {
                Toast.makeText(context, R.string.be_patient, Toast.LENGTH_SHORT).show();
                return;
            }
            if (settingsHelper.getBoolean(MARK_AS_SEEN)
                    && oldFeedStory instanceof FeedStoryModel
                    && viewModel instanceof FeedStoriesViewModel) {
                final FeedStoriesViewModel feedStoriesViewModel = (FeedStoriesViewModel) viewModel;
                final FeedStoryModel oldFeedStoryModel = (FeedStoryModel) oldFeedStory;
                if (!oldFeedStoryModel.isFullyRead()) {
                    oldFeedStoryModel.setFullyRead(true);
                    final List<FeedStoryModel> models = feedStoriesViewModel.getList().getValue();
                    final List<FeedStoryModel> modelsCopy = models == null ? new ArrayList<>() : new ArrayList<>(models);
                    modelsCopy.set(currentFeedStoryIndex, oldFeedStoryModel);
                    feedStoriesViewModel.getList().postValue(models);
                }
            }
            fetching = true;
            binding.btnBackward.setVisibility(currentFeedStoryIndex == 1 && backward ? View.INVISIBLE : View.VISIBLE);
            binding.btnForward.setVisibility(last ? View.INVISIBLE : View.VISIBLE);
            currentFeedStoryIndex = backward ? (currentFeedStoryIndex - 1) : (currentFeedStoryIndex + 1);
            resetView();
        }
    }

    /**
     * Parses the Story's media ID. For user stories this is a number, but for archive stories
     * this is "archiveDay:" plus a number.
     */
    private static String parseStoryMediaId(String rawId) {
        final String regex = "(?:archiveDay:)?(.+)";
        final Pattern pattern = Pattern.compile(regex);
        final Matcher matcher = pattern.matcher(rawId);

        if (matcher.matches() && matcher.groupCount() >= 1) {
            return matcher.group(1);
        }

        return rawId;
    }
}
