// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.content.browser;

import android.content.Context;
import android.content.pm.PackageManager;
import android.media.MediaMetadataRetriever;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace;
import org.chromium.base.PathUtils;

import java.io.File;
import java.util.HashMap;

/**
 * Java counterpart of android MediaResourceGetter.
 */
@JNINamespace("content")
class MediaResourceGetter {

    private static final String TAG = "MediaResourceGetter";

    private static class MediaMetadata {
        private final int mDurationInMilliseconds;
        private final int mWidth;
        private final int mHeight;
        private final boolean mSuccess;

        private MediaMetadata(int durationInMilliseconds, int width, int height, boolean success) {
            mDurationInMilliseconds = durationInMilliseconds;
            mWidth = width;
            mHeight = height;
            mSuccess = success;
        }

        @CalledByNative("MediaMetadata")
        private int getDurationInMilliseconds() { return mDurationInMilliseconds; }

        @CalledByNative("MediaMetadata")
        private int getWidth() { return mWidth; }

        @CalledByNative("MediaMetadata")
        private int getHeight() { return mHeight; }

        @CalledByNative("MediaMetadata")
        private boolean isSuccess() { return mSuccess; }
    }

    @CalledByNative
    private static MediaMetadata extractMediaMetadata(Context context, String url, String cookies) {
        int durationInMilliseconds = 0;
        int width = 0;
        int height = 0;
        boolean success = false;
        // TODO(qinmin): use ConnectionTypeObserver to listen to the network type change.
        ConnectivityManager mConnectivityManager =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (mConnectivityManager != null) {
            if (context.checkCallingOrSelfPermission(
                    android.Manifest.permission.ACCESS_NETWORK_STATE) !=
                    PackageManager.PERMISSION_GRANTED) {
                return new MediaMetadata(0, 0, 0, false);
            }

            NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
            if (info == null) {
                return new MediaMetadata(durationInMilliseconds, width, height, success);
            }
            switch (info.getType()) {
                case ConnectivityManager.TYPE_ETHERNET:
                case ConnectivityManager.TYPE_WIFI:
                    break;
                case ConnectivityManager.TYPE_WIMAX:
                case ConnectivityManager.TYPE_MOBILE:
                default:
                    return new MediaMetadata(durationInMilliseconds, width, height, success);
            }
        }

        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            Uri uri = Uri.parse(url);
            String scheme = uri.getScheme();
            if (scheme == null || scheme.equals("file")) {
                File file = new File(uri.getPath());
                String path = file.getAbsolutePath();
                if (file.exists() && (path.startsWith("/mnt/sdcard/") ||
                        path.startsWith("/sdcard/") ||
                        path.startsWith(PathUtils.getExternalStorageDirectory()))) {
                    retriever.setDataSource(path);
                } else {
                    Log.e(TAG, "Unable to read file: " + url);
                    return new MediaMetadata(durationInMilliseconds, width, height, success);
                }
            } else {
                HashMap<String, String> headersMap = new HashMap<String, String>();
                if (!TextUtils.isEmpty(cookies)) {
                    headersMap.put("Cookie", cookies);
                }
                retriever.setDataSource(url, headersMap);
            }
            durationInMilliseconds = Integer.parseInt(
                    retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
            width = Integer.parseInt(
                    retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
            height = Integer.parseInt(
                    retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
            success = true;
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Invalid url: " + e);
        } catch (RuntimeException e) {
            Log.e(TAG, "Invalid url: " + e);
        }
        return new MediaMetadata(durationInMilliseconds, width, height, success);
    }
}

@@ -4227,70 +4227,22 @@
     
-durationInMilliseconds = Integer.parseInt(%0A                   
+String value =
  ret
@@ -4309,17 +4309,16 @@
 URATION)
-)
 ;%0A      
@@ -4323,21 +4323,73 @@
         
-width
+if (value != null) %7B%0A              durationInMilliseconds
  = Integ
@@ -4392,32 +4392,39 @@
 nteger.parseInt(
+value);
 %0A               
@@ -4410,32 +4410,36 @@
 lue);%0A          
+  %7D%0A
           retrie
@@ -4423,32 +4423,42 @@
      %7D%0A         
+   value =
  retriever.extra
@@ -4516,17 +4516,16 @@
 O_WIDTH)
-)
 ;%0A      
@@ -4530,22 +4530,56 @@
         
-height
+if (value != null) %7B%0A              width
  = Integ
@@ -4590,16 +4590,23 @@
 arseInt(
+value);
 %0A       
@@ -4598,32 +4598,38 @@
 value);%0A        
+    %7D%0A
             retr
@@ -4615,32 +4615,40 @@
    %7D%0A           
+ value =
  retriever.extra
@@ -4707,18 +4707,112 @@
 _HEIGHT)
-)
 ;
+%0A            if (value != null) %7B%0A              height = Integer.parseInt(value);%0A            %7D
 %0A       

Check if MediaMetadataRetriever returns null strings