using UnityEngine;
using UnityEngine.UI;
using System.Collections;

using System.IO;
using Module.Log;

public class ImageManagerRoot : UIControllerBase<ImageManagerRoot>
{
    #region 

    public static void ShowImageCutStatic(CuttedPhoto callBack)
    {
        UIManager.ShowUI(UIInfo.ImageManagerRoot, (sucess, param) =>
        {
            ImageManagerRoot.Instance()._CuttedPhotoCallback = callBack;
            ImageManagerRoot.Instance().SelectCuttedPhote();
        });
    }

    public static void ShowImageCameraStatic(CuttedPhoto callBack)
    {
        UIManager.ShowUI(UIInfo.ImageManagerRoot, (sucess, param) =>
        {
            ImageManagerRoot.Instance()._CuttedPhotoCallback = callBack;
            ImageManagerRoot.Instance().SelectWebCamTexture();
        });
    }

    public void Start()
    {
        SetInstance(this);

        InitReciver();
    }

    public void Close()
    {
        UIManager.CloseUI(UIInfo.ImageManagerRoot);
    }

    public void Update()
    {
        CameraUpdate();
        UpdateLoadImage();
    }

    #endregion

    #region load image


    void InitReciver()
    {
        var uiGO = GameObject.Find("UI Root");
        var imageReciver = uiGO.GetComponent<ImageSelectReciver>();
        if (imageReciver == null)
            imageReciver = uiGO.AddComponent<ImageSelectReciver>();
        imageReciver._ImageSelectTool = this;
    }

    public void SelectCuttedPhote()
    {
        _CamPanel.SetActive(false);
        _CutImgPanel.SetActive(false);
        //gameObject.SetActive(true);
        //InitReciver();
        _OrgPhoto = null;
        _OrgPhotoImage.texture = null;
        int maxSize = Screen.width * 2;
        maxSize = Mathf.Min(2560, maxSize);
#if UNITY_IPHONE && !UNITY_EDITOR

        //调用插件自带接口,拉取相册,内部有区分平台
        NativeGallery.Permission permission = NativeGallery.GetImageFromGallery((path) =>
        {
            Debug.Log("Image path: " + path);
            if (path != null)
            {
                // 此Action为选取图片后的回调,返回一个Texture2D 
                Texture2D texture = NativeGallery.LoadImageAtPath(path, maxSize);
                if (texture == null)
                {
                    Debug.Log("Couldn't load texture from " + path);
                    return;
                }
                _OrgPhoto = texture;
                Debug.Log(texture.name);
                //var readableTex = duplicateTexture(texture);
                //ShowImageCut(readableTex);
            }
        }, "选择图片", "image/png", maxSize);

        Debug.Log("Permission result: " + permission);
    
#elif UNITY_ANDROID && !UNITY_EDITOR

        NativeGallery.Permission permission = NativeGallery.GetImageFromGallery((path) =>
        {
            Debug.Log("Image path: " + path);
            if (path != null)
            {
                // 此Action为选取图片后的回调,返回一个Texture2D 
                Texture2D texture = NativeGallery.LoadImageAtPath(path, maxSize);
                if (texture == null)
                {
                    Debug.Log("Couldn't load texture from " + path);
                    return;
                }
                _OrgPhoto = texture;
                Debug.Log(texture.name);
                //var readableTex = duplicateTexture(texture);
                //ShowImageCut(readableTex);
            }
        }, "选择图片", "image/png", maxSize);

        Debug.Log("Permission result: " + permission);
#else
        LoadWindFile.LoadImage(GetImagePath);
#endif

    }

    private Texture2D duplicateTexture(Texture2D source)
    {
        RenderTexture renderTex = RenderTexture.GetTemporary(
                    source.width,
                    source.height,
                    0,
                    RenderTextureFormat.Default,
                    RenderTextureReadWrite.Linear);

        Graphics.Blit(source, renderTex);
        RenderTexture previous = RenderTexture.active;
        RenderTexture.active = renderTex;
        Texture2D readableText = new Texture2D(source.width, source.height);
        readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
        readableText.Apply();
        RenderTexture.active = previous;
        RenderTexture.ReleaseTemporary(renderTex);
        return readableText;
    }

    public void GetImagePath(string path)
    {
        if (string.IsNullOrEmpty(path))
            return;
        
        GuiTextDebug.debug("GetImagePath:" + path);
        StartCoroutine(LoadLocalImage(path));
    }

    public void UpdateLoadImage()
    {
        if (_OrgPhoto != null && _OrgPhotoImage.texture == null)
        {
            var readableTex = duplicateTexture(_OrgPhoto);
            ShowImageCut(readableTex);
        }
    }

    IEnumerator LoadLocalImage(string fileName)
    {
        string filePath = "";
#if UNITY_IPHONE && !UNITY_EDITOR
        filePath = "file://" + fileName;
#elif UNITY_ANDROID && !UNITY_EDITOR
        filePath = "file://" + fileName;
#else
        filePath = "file://" + fileName;
#endif

        string exName = Path.GetExtension(fileName);
        exName = exName.ToLower();
        if (!exName.Equals(".jpg") && !exName.Equals(".png"))
        {
            LogModule.ErrorLog("Img file:" + fileName + ", load error");
            GUIData.AddNotifyData("#{39030}");
            yield break;
        }

        WWW wwwTexture = new WWW(filePath);

        LogModule.DebugLog(wwwTexture.url);

        yield return wwwTexture;

        if (!string.IsNullOrEmpty(wwwTexture.error))
        {
            GUIData.AddNotifyData("#{39031}");
            LogModule.ErrorLog("LoadImageError:" + wwwTexture.error + ", " + fileName);
        }
        else
        {
            var texture2d = wwwTexture.texture;
            ShowImageCut(texture2d);
        }
    }

    #endregion

    #region camera image

    public GameObject _CamPanel;
    public RawImage _CameraTexture;
    private WebCamTexture _WebCamTexture;

    public void SelectWebCamTexture()
    {
        StartCoroutine(StartWebCam());
    }

    public void CameraUpdate()
    {
        if (_WebCamTexture != null)
        {
            if (Screen.orientation == ScreenOrientation.LandscapeRight)
            {
                _CameraTexture.transform.rotation = Quaternion.Euler(0, 0, 180);
            }
            else
            {
                _CameraTexture.transform.rotation = Quaternion.Euler(0, 0, 0);
            }
        }
    }

    public IEnumerator StartWebCam()
    {
        yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
        if (Application.HasUserAuthorization(UserAuthorization.WebCam))
        {
            WebCamDevice[] devices = WebCamTexture.devices;
            if (devices.Length == 0)
            {
                GUIData.AddNotifyData(GCGame.Table.StrDictionary.GetClientDictionaryString("#{39023}"));
                Close();
                yield break;
            }
            _CamPanel.gameObject.SetActive(true);
            var deviceName = devices[0].name;
            _WebCamTexture = new WebCamTexture(deviceName, Screen.width, Screen.height, 12);
            _WebCamTexture.Play();
            _CameraTexture.texture = _WebCamTexture;
        }
        else
        {
            GUIData.AddNotifyData(GCGame.Table.StrDictionary.GetClientDictionaryString("#{39023}"));
            Close();
        }
    }

    public void OnBtnCameraOk()
    {
        Texture2D bla = new Texture2D(_WebCamTexture.width, _WebCamTexture.height);
        if (Screen.orientation == ScreenOrientation.LandscapeRight)
        {
            for (int i = 0; i < _WebCamTexture.width; ++i)
            {
                for (int j = 0; j < _WebCamTexture.height; ++j)
                {
                    bla.SetPixel(i, j, _WebCamTexture.GetPixel(_WebCamTexture.width - i, _WebCamTexture.height - j));
                }
            }
        }
        else
        {
            for (int i = 0; i < _WebCamTexture.width; ++i)
            {
                for (int j = 0; j < _WebCamTexture.height; ++j)
                {
                    bla.SetPixel(i, j, _WebCamTexture.GetPixel(i, j));
                }
            }
        }
        bla.Apply();

        if (bla != null)
        {
            ShowImageCut(bla);
        }
        else
        {
            Close();
        }

        _CamPanel.gameObject.SetActive(false);
        _WebCamTexture.Stop();
        _WebCamTexture = null;
    }

    #endregion

    #region cutted image

    public GameObject _CutImgPanel;
    public RawImage _OrgPhotoImage;
    public Vector2 _CutSize;

    private int _ScollImageXMin;
    private int _ScollImageXMax;
    private int _ScollImageYMin;
    private int _ScollImageYMax;
    private Texture2D _OrgPhoto;

    public delegate void CuttedPhoto(Texture2D cuttedImg);
    public CuttedPhoto _CuttedPhotoCallback;

    private Vector2 _TextureOrgSize;
    private float _LargeRate;
    private float _SmallRate;
    private float _CurRate;

    private static float _MaxOrgSizeRate = 2f;
    private static float _SizeStep = 0.1f;

    public void ShowImageCut(Texture2D orgPhoto)
    {
        if (orgPhoto == null)
        {
            Close();
            return;
        }
        _CutImgPanel.SetActive(true);
        _OrgPhoto = orgPhoto;
        _OrgPhotoImage.texture = orgPhoto;
        _OrgPhotoImage.color = new Color(1, 1, 1);
        //_OrgPhotoImage.texture = orgPhoto;
        _OrgPhotoImage.rectTransform.sizeDelta = new Vector2(orgPhoto.width, orgPhoto.height);
        _OrgPhotoImage.rectTransform.anchoredPosition = Vector2.zero;

        _TextureOrgSize = new Vector2(orgPhoto.width, orgPhoto.height);
        Debug.Log("_TextureOrgSize:" + _TextureOrgSize);
        //最大放大倍数,原图的2.5倍或屏幕的两倍;缩小倍数,cutSizeX
        if (_TextureOrgSize.x > _TextureOrgSize.y)
        {
            _LargeRate = Mathf.Min(_MaxOrgSizeRate, Screen.width * 2 / _TextureOrgSize.x);
            _LargeRate = Mathf.Max(_CutSize.x / _TextureOrgSize.x, _LargeRate);

            _SmallRate = _CutSize.y / _TextureOrgSize.y;

            if (_TextureOrgSize.x > Screen.width)
            {
                _CurRate = Screen.width / _TextureOrgSize.x;
            }
            else if (_TextureOrgSize.y < _CutSize.y)
            {
                _CurRate = _TextureOrgSize.y / _CutSize.y;
            }
            else
            {
                _CurRate = 1;
            }
        }
        else
        {
            _LargeRate = Mathf.Min(_MaxOrgSizeRate, Screen.height * 2 / _TextureOrgSize.y);
            _LargeRate = Mathf.Max(_CutSize.y / _TextureOrgSize.y, _LargeRate);

            _SmallRate = _CutSize.x / _TextureOrgSize.x;

            if (_TextureOrgSize.y > Screen.height)
            {
                _CurRate = Screen.height / _TextureOrgSize.y;
            }
            else if (_TextureOrgSize.x < _CutSize.x)
            {
                _CurRate = _TextureOrgSize.x / _CutSize.x;
            }
            else
            {
                _CurRate = 1;
            }
        }

        if (_LargeRate < _SmallRate)
        {
            _LargeRate = _SmallRate;
        }

        _CurRate = Mathf.Clamp(_CurRate, _SmallRate, _LargeRate);

        _OrgPhotoImage.rectTransform.sizeDelta = new Vector2(_TextureOrgSize.x * _CurRate, _TextureOrgSize.y * _CurRate);
        Debug.Log("LargeRate:" + _LargeRate + ", SmallRate:" + _SmallRate + ", CurRate:" + _CurRate);

        Resize();
    }

    public void Resize()
    {
        _ScollImageXMin = (int)(-(_TextureOrgSize.x * _CurRate * 0.5f - _CutSize.x * 0.5f));
        _ScollImageXMax = (int)(-_ScollImageXMin);
        if (_TextureOrgSize.x * _CurRate < _CutSize.x)
        {
            _ScollImageXMin = 0;
            _ScollImageXMax = 0;
        }

        _ScollImageYMin = (int)(-(_TextureOrgSize.y * _CurRate * 0.5f - _CutSize.y * 0.5f));
        _ScollImageYMax = (int)(-_ScollImageYMin);
        if (_TextureOrgSize.y * _CurRate < _CutSize.y)
        {
            _ScollImageYMin = 0;
            _ScollImageYMax = 0;
        }

        Debug.Log("_ScollImageYMin:" + _ScollImageXMin + "," + _ScollImageYMin);
    }

    public void ScollImage(Vector2 direct)
    {
        var modifyDirect = direct;

        Vector2 newAnchorPos = _OrgPhotoImage.rectTransform.anchoredPosition + modifyDirect;
        newAnchorPos.x = Mathf.Clamp(newAnchorPos.x, _ScollImageXMin, _ScollImageXMax);
        newAnchorPos.y = Mathf.Clamp(newAnchorPos.y, _ScollImageYMin, _ScollImageYMax);
        _OrgPhotoImage.rectTransform.anchoredPosition = newAnchorPos;
    }

    public void CutImage()
    {
        /*var cameraTexture = RenderTexturePool.Instance.GetRenderTexture(new Vector2(1280, 760));
        var mainCamera = UIManager.Instance().UICamera;
        Texture2D readableText = new Texture2D(cameraTexture.width, cameraTexture.height);
        if (mainCamera != null)
        {
            var temp = mainCamera.targetTexture;
            mainCamera.targetTexture = cameraTexture;
            var mainCameraState = mainCamera.enabled;
            mainCamera.enabled = true;
            mainCamera.Render();

            RenderTexture.active = cameraTexture;
            readableText.ReadPixels(new Rect(0, 0, cameraTexture.width, cameraTexture.height), 0, 0);
            readableText.Apply();

            mainCamera.enabled = mainCameraState;
            mainCamera.targetTexture = temp;
        }

        
        Debug.Log("readableText:" + readableText.width + "," + readableText.height);

        int cutSizeX = (int)_CutSize.x;
        int cutSizeY = (int)_CutSize.y;
        Texture2D rectPhoto = new Texture2D(cutSizeX, cutSizeY, TextureFormat.ARGB32, true);
        int startPosx = (int)(readableText.width * 0.5f - cutSizeX * 0.5f);
        int startPosY = (int)(readableText.height * 0.5f - cutSizeY * 0.5f);
        //int startPosx = 0;
        //int startPosY = 0;
        for (int i = 0; i < cutSizeX; ++i)
        {
            for (int j = 0; j < cutSizeY; ++j)
            {
                var color = readableText.GetPixel(i + startPosx, j + startPosY);
                rectPhoto.SetPixel(i, j, color);
                //LogModule.DebugLog("Color:" + color);
            }
        }*/

        
        

        int cutSizeX = Mathf.Min((int)_CutSize.x, _OrgPhoto.width);
        int cutSizeY = Mathf.Min((int)_CutSize.y, _OrgPhoto.height);
        if (cutSizeX > cutSizeY)
        {
            cutSizeX = cutSizeY;
        }
        else
        {
            cutSizeY = cutSizeX;
        }

        int cutPosX = (int)-((_OrgPhotoImage.rectTransform.anchoredPosition.x + _ScollImageXMin) / _CurRate);
        int cutPosY = (int)-((_OrgPhotoImage.rectTransform.anchoredPosition.y + _ScollImageYMin) / _CurRate);
        LogModule.DebugLog("CutPos:" + cutPosX + "," + cutPosY);

        LogModule.DebugLog("CutSize:" + cutSizeX + "," + cutSizeY);
        Texture2D rectPhoto = new Texture2D(cutSizeX, cutSizeY, TextureFormat.ARGB32, true);
        for (int i = 0; i < cutSizeX; ++i)
        {
            for (int j = 0; j < cutSizeY; ++j)
            {
                if (cutSizeX < _OrgPhoto.width && cutSizeY < _OrgPhoto.height)
                {
                    var color = _OrgPhoto.GetPixel((int)(i / _CurRate + cutPosX), (int)(j / _CurRate + cutPosY));
                    rectPhoto.SetPixel(i, j, color);
                }
                else
                {
                    var color = _OrgPhoto.GetPixel((int)(i + cutPosX), (int)(j + cutPosY));
                    rectPhoto.SetPixel(i, j, color);
                }
            }
        }

        rectPhoto.Apply();

        if (_CuttedPhotoCallback != null)
        {
            _CuttedPhotoCallback.Invoke(rectPhoto);
        }
        Close();

        //StartCoroutine(ApplyCuttedTexture(rectPhoto));
    }



    public void OnBtnTextureExpend()
    {
        _CurRate += _SizeStep;
        _CurRate = Mathf.Clamp(_CurRate, _SmallRate, _LargeRate);

        _OrgPhotoImage.rectTransform.sizeDelta = new Vector2(_TextureOrgSize.x * _CurRate, _TextureOrgSize.y * _CurRate);

        Resize();
        ScollImage(Vector2.zero);
    }

    public void OnBtnTextureNarrow()
    {
        _CurRate -= _SizeStep;
        _CurRate = Mathf.Clamp(_CurRate, _SmallRate, _LargeRate);
        _OrgPhotoImage.rectTransform.sizeDelta = new Vector2(_TextureOrgSize.x * _CurRate, _TextureOrgSize.y * _CurRate);

        Resize();
        ScollImage(Vector2.zero);
    }

    private IEnumerator ApplyCuttedTexture(Texture2D rectPhoto)
    {
        yield return new WaitForEndOfFrame();

        rectPhoto.Apply();

        if (_CuttedPhotoCallback != null)
        {
            _CuttedPhotoCallback.Invoke(rectPhoto);
        }
        gameObject.SetActive(false);
    }

    #endregion
}