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

package com.example.android.scopeddirectoryaccess;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.provider.DocumentsContract;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * Fragment that displays the directory contents.
 */
public class ScopedDirectoryAccessFragment extends Fragment {

    private static final String DIRECTORY_ENTRIES_KEY = "directory_entries";
    private static final String SELECTED_DIRECTORY_KEY = "selected_directory";
    private static final int OPEN_DIRECTORY_REQUEST_CODE = 1;

    private static final String[] DIRECTORY_SELECTION = new String[]{
            DocumentsContract.Document.COLUMN_DISPLAY_NAME,
            DocumentsContract.Document.COLUMN_MIME_TYPE,
            DocumentsContract.Document.COLUMN_DOCUMENT_ID,
    };

    private Activity mActivity;
    private StorageManager mStorageManager;
    private TextView mCurrentDirectoryTextView;
    private TextView mNothingInDirectoryTextView;
    private TextView mPrimaryVolumeNameTextView;
    private Spinner mDirectoriesSpinner;
    private DirectoryEntryAdapter mAdapter;
    private ArrayList<DirectoryEntry> mDirectoryEntries;

    public static ScopedDirectoryAccessFragment newInstance() {
        ScopedDirectoryAccessFragment fragment = new ScopedDirectoryAccessFragment();
        return fragment;
    }

    public ScopedDirectoryAccessFragment() {
        // Required empty public constructor
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mActivity = getActivity();
        mStorageManager = mActivity.getSystemService(StorageManager.class);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == OPEN_DIRECTORY_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
            getActivity().getContentResolver().takePersistableUriPermission(data.getData(),
                    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            updateDirectoryEntries(data.getData());
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_scoped_directory_access, container, false);
    }

    @Override
    public void onViewCreated(final View rootView, Bundle savedInstanceState) {
        super.onViewCreated(rootView, savedInstanceState);

        mCurrentDirectoryTextView = (TextView) rootView
                .findViewById(R.id.textview_current_directory);
        mNothingInDirectoryTextView = (TextView) rootView
                .findViewById(R.id.textview_nothing_in_directory);
        mPrimaryVolumeNameTextView = (TextView) rootView
                .findViewById(R.id.textview_primary_volume_name);

        // Set onClickListener for the primary volume
        Button openPictureButton = (Button) rootView
                .findViewById(R.id.button_open_directory_primary_volume);
        openPictureButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String selected = mDirectoriesSpinner.getSelectedItem().toString();
                String directoryName = getDirectoryName(selected);
                StorageVolume storageVolume = mStorageManager.getPrimaryStorageVolume();
                Intent intent = storageVolume.createAccessIntent(directoryName);
                startActivityForResult(intent, OPEN_DIRECTORY_REQUEST_CODE);
            }
        });

        // Set onClickListener for the external volumes if exists
        List<StorageVolume> storageVolumes = mStorageManager.getStorageVolumes();
        LinearLayout containerVolumes = (LinearLayout) mActivity
                .findViewById(R.id.container_volumes);
        for (final StorageVolume volume : storageVolumes) {
            String volumeDescription = volume.getDescription(mActivity);
            if (volume.isPrimary()) {
                // Primary volume area is already added...
                if (volumeDescription != null) {
                    // ...but with a default name: set it to the real name when available.
                    mPrimaryVolumeNameTextView.setText(volumeDescription);
                }
                continue;
            }
            LinearLayout volumeArea = (LinearLayout) mActivity.getLayoutInflater()
                    .inflate(R.layout.volume_entry, containerVolumes);
            TextView volumeName = (TextView) volumeArea.findViewById(R.id.textview_volume_name);
            volumeName.setText(volumeDescription);
            Button button = (Button) volumeArea.findViewById(R.id.button_open_directory);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String selected = mDirectoriesSpinner.getSelectedItem().toString();
                    String directoryName = getDirectoryName(selected);
                    Intent intent = volume.createAccessIntent(directoryName);
                    startActivityForResult(intent, OPEN_DIRECTORY_REQUEST_CODE);
                }
            });
        }
        RecyclerView recyclerView = (RecyclerView) rootView
                .findViewById(R.id.recyclerview_directory_entries);
        if (savedInstanceState != null) {
            mDirectoryEntries = savedInstanceState.getParcelableArrayList(DIRECTORY_ENTRIES_KEY);
            mCurrentDirectoryTextView.setText(savedInstanceState.getString(SELECTED_DIRECTORY_KEY));
            mAdapter = new DirectoryEntryAdapter(mDirectoryEntries);
            if (mAdapter.getItemCount() == 0) {
                mNothingInDirectoryTextView.setVisibility(View.VISIBLE);
            }
        } else {
            mDirectoryEntries = new ArrayList<>();
            mAdapter = new DirectoryEntryAdapter();
        }
        recyclerView.setAdapter(mAdapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mDirectoriesSpinner = (Spinner) rootView.findViewById(R.id.spinner_directories);
        ArrayAdapter<CharSequence> directoriesAdapter = ArrayAdapter
                .createFromResource(getActivity(),
                        R.array.directories, android.R.layout.simple_spinner_item);
        directoriesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mDirectoriesSpinner.setAdapter(directoriesAdapter);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(SELECTED_DIRECTORY_KEY, mCurrentDirectoryTextView.getText().toString());
        outState.putParcelableArrayList(DIRECTORY_ENTRIES_KEY, mDirectoryEntries);
    }

    private void updateDirectoryEntries(Uri uri) {
        mDirectoryEntries.clear();
        ContentResolver contentResolver = getActivity().getContentResolver();
        Uri docUri = DocumentsContract.buildDocumentUriUsingTree(uri,
                DocumentsContract.getTreeDocumentId(uri));
        Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri,
                DocumentsContract.getTreeDocumentId(uri));

        try (Cursor docCursor = contentResolver
                .query(docUri, DIRECTORY_SELECTION, null, null, null)) {
            while (docCursor != null && docCursor.moveToNext()) {
                mCurrentDirectoryTextView.setText(docCursor.getString(docCursor.getColumnIndex(
                        DocumentsContract.Document.COLUMN_DISPLAY_NAME)));
            }
        }

        try (Cursor childCursor = contentResolver
                .query(childrenUri, DIRECTORY_SELECTION, null, null, null)) {
            while (childCursor != null && childCursor.moveToNext()) {
                DirectoryEntry entry = new DirectoryEntry();
                entry.fileName = childCursor.getString(childCursor.getColumnIndex(
                        DocumentsContract.Document.COLUMN_DISPLAY_NAME));
                entry.mimeType = childCursor.getString(childCursor.getColumnIndex(
                        DocumentsContract.Document.COLUMN_MIME_TYPE));
                mDirectoryEntries.add(entry);
            }

            if (mDirectoryEntries.isEmpty()) {
                mNothingInDirectoryTextView.setVisibility(View.VISIBLE);
            } else {
                mNothingInDirectoryTextView.setVisibility(View.GONE);
            }
            mAdapter.setDirectoryEntries(mDirectoryEntries);
            mAdapter.notifyDataSetChanged();
        }
    }

    private String getDirectoryName(String name) {
        switch (name) {
            case "ALARMS":
                return Environment.DIRECTORY_ALARMS;
            case "DCIM":
                return Environment.DIRECTORY_DCIM;
            case "DOCUMENTS":
                return Environment.DIRECTORY_DOCUMENTS;
            case "DOWNLOADS":
                return Environment.DIRECTORY_DOWNLOADS;
            case "MOVIES":
                return Environment.DIRECTORY_MOVIES;
            case "MUSIC":
                return Environment.DIRECTORY_MUSIC;
            case "NOTIFICATIONS":
                return Environment.DIRECTORY_NOTIFICATIONS;
            case "PICTURES":
                return Environment.DIRECTORY_PICTURES;
            case "PODCASTS":
                return Environment.DIRECTORY_PODCASTS;
            case "RINGTONES":
                return Environment.DIRECTORY_RINGTONES;
            default:
                throw new IllegalArgumentException("Invalid directory representation: " + name);
        }
    }
}