content: //
  //  Copyright (c) 2014 VK.com
  //
  //  Permission is hereby granted, free of charge, to any person obtaining a copy of
  //  this software and associated documentation files (the "Software"), to deal in
  //  the Software without restriction, including without limitation the rights to
  //  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  //  the Software, and to permit persons to whom the Software is furnished to do so,
  //  subject to the following conditions:
  //
  //  The above copyright notice and this permission notice shall be included in all
  //  copies or substantial portions of the Software.
  //
  //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  //  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  //  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  //  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  //  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  
  /**
   * PhotoSize.java
   * VK Dev
   *
   * Created by Babichev Vitaly on 03.10.13.
   * Copyright (c) 2013 VK. All rights reserved.
   */
  package com.vk.sdk.api.model;
  
  import android.os.Parcel;
  import android.os.Parcelable;
  import android.text.TextUtils;
  
  import org.json.JSONException;
  import org.json.JSONObject;
  
  /**
   * Describes an photo info in <a href="http://vk.com/dev/photo_sizes">special format<a/>.
   *
   * Some methods returns information about copies of the original image in different sizes,
   * Represented as an array of sizes, containing a description of the objects of this class.
   *
   * <b>Sizes value example:</b>
   *
   * Original photo — https://pp.vk.me/c323930/v323930021/53fb/1VrEC2eSkZQ.jpg,1280x856px,
   * "width/height" ratio is 1.495327102803738
   *
   * <code>
   sizes: [{
      src: http://cs323930.vk.me/v323930021/53f7/OwV0l2YFJ7s.jpg
      width: 75,
      height: 50,
      type: 's'
      }, {
      src: http://cs323930.vk.me/v323930021/53f8/qX8MRNyUPqg.jpg,
      width: 130,
      height: 87,
      type: 'm'
      }, {
      src: http://cs323930.vk.me/v323930021/53f9/7fBJyr9OHMA.jpg,
      width: 604,
      height: 404,
      type: 'x'
      }, {
      src: http://cs323930.vk.me/v323930021/53fa/bskHpsuH6sM.jpg,
      width: 807,
      height: 540,
      type: 'y'
      }, {
      src: http://cs323930.vk.me/v323930021/53fb/1VrEC2eSkZQ.jpg,
      width: 1280,
      height: 856,
      type: 'z'
      }, {
      src: http://cs323930.vk.me/v323930021/53fc/iAl-TIHfRDY.jpg,
      width: 130,
      height: 87,
      type: 'o'
      }, {
      src: http://cs323930.vk.me/v323930021/53fd/qjD0fbHkgmI.jpg,
      width: 200,
      height: 134,
      type: 'p'
      }, {
      src: http://cs323930.vk.me/v323930021/53fe/3d2nCvvKQfw.jpg,
      width: 320,
      height: 214,
      type: 'q'
      }, {
      src: http://cs323930.vk.me/v323930021/53ff/uK_Nj34SIY8.jpg,
      width: 510,
      height: 341,
      type: 'r'
      }]
   * </code>
   *
   */
  public class VKApiPhotoSize extends VKApiModel implements Comparable<VKApiPhotoSize>, Parcelable, Identifiable {
  
      /**
       * Proportional copy with 75px max width
       */
      public final static char S = 's';
  
      /**
       *  Proportional copy with 130px max width
       */
      public final static char M = 'm';
  
      /**
       * Proportional copy with 604px max width
       */
      public final static char X = 'x';
  
      /**
       * Proportional copy with 807px max width
       */
      public final static char Y = 'y';
  
      /**
       * If original image's "width/height" ratio is less or equal to 3:2, then proportional
       * copy with 130px max width. If original image's "width/height" ratio is more than 3:2,
       * then copy of cropped by left side image with 130px max width and 3:2 sides ratio.
       */
      public final static char O = 'o';
  
      /**
       * If original image's "width/height" ratio is less or equal to 3:2, then proportional
       * copy with 200px max width. If original image's "width/height" ratio is more than 3:2,
       * then copy of cropped by left side image with 200px max width and 3:2 sides ratio.
       */
      public final static char P = 'p';
  
      /**
       * If original image's "width/height" ratio is less or equal to 3:2, then proportional
       * copy with 320px max width. If original image's "width/height" ratio is more than 3:2,
       * then copy of cropped by left side image with 320px max width and 3:2 sides ratio.
       */
      public final static char Q = 'q';
  
      /**
       * Proportional copy with 1280x1024px max size
       */
      public final static char Z = 'z';
  
      /**
       * Proportional copy with 2560x2048px max size
       */
      public final static char W = 'w';
  
      /**
       * Url of image
       */
      public String src;
  
      /**
       * Width of image in pixels
       */
      public int width;
  
      /**
       * Height of image in pixels
       */
      public int height;
  
      /**
       * Designation of size and proportions copy, @see {{@link #S}, {@link #M}, {@link #X}, {@link #O}, {@link #P}, {@link #Q}, {@link #Y}, {@link #Z}, {@link #W}}
       */
      public char type;
  
      private VKApiPhotoSize() {
  
      }
  
      private VKApiPhotoSize(Parcel in) {
          this.src = in.readString();
          this.width = in.readInt();
          this.height = in.readInt();
          this.type = (char) in.readInt();
      }
  
      @Override
      public int compareTo(VKApiPhotoSize another) {
          // Так как основной превалирующий элемент в фотографиях именно ширина и все фотографии пропорциональны,
          // то сравниваем именно по ней
          return this.width < another.width ? -1 : (this.width == another.width ? 0 : 1);
      }
  
      @Override
      public int describeContents() {
          return 0;
      }
  
      @Override
      public void writeToParcel(Parcel dest, int flags) {
          dest.writeString(this.src);
          dest.writeInt(this.width);
          dest.writeInt(this.height);
          dest.writeInt((int)this.type);
      }
  
      @Override
      public int getId() {
          return 0;
      }
  
      public static Creator<VKApiPhotoSize> CREATOR = new Creator<VKApiPhotoSize>() {
          public VKApiPhotoSize createFromParcel(Parcel source) {
              return new VKApiPhotoSize(source);
          }
  
          public VKApiPhotoSize[] newArray(int size) {
              return new VKApiPhotoSize[size];
          }
      };
  
  	public VKApiPhotoSize(JSONObject from) throws JSONException
  	{
  		parse(from, 0, 0);
  	}
      /**
       * Creates dimension from {@code source}. Used in parsing.
       * If size is not specified copies calculates them based on internal algorithms.
       * @param source object in format, returned VK API, which is generated from the dimension
       * @param originalWidth original image width in pixels
       * @param originalHeight original image height in pixels
       */
      public static VKApiPhotoSize parse(JSONObject source, int originalWidth, int originalHeight) {
          VKApiPhotoSize result = new VKApiPhotoSize();
          result.src = source.optString("src");
          result.width = source.optInt("width");
          result.height = source.optInt("height");
          String type = source.optString("type");
          if(!TextUtils.isEmpty(type)) {
              result.type = type.charAt(0);
          }
          // Казалось бы, теперь можно с чистой советью закончить метод.
          // Но нет, оказывается, width и height не просчитывается на некоторых серверах ВК.
          // Приходится гадать на кофейной гуще.
          if(result.width == 0 || result.height == 0) {
              fillDimensions(result, originalWidth, originalHeight);
          }
          return result;
      }
  
      /*
       * Устанавливает размерность исходя из размеров оригинала и типа изображения.
       */
      private static void fillDimensions(VKApiPhotoSize result, int originalWidth, int originalHeight) {
          float ratio = (float) originalWidth / originalHeight;
          switch (result.type) {
              case S: {
                  fillDimensionSMXY(result, ratio, Math.min(originalWidth, 75));
              } break;
              case M: {
                  fillDimensionSMXY(result, ratio, Math.min(originalWidth, 130));
              } break;
              case X: {
                  fillDimensionSMXY(result, ratio, Math.min(originalWidth, 604));
              } break;
              case Y: {
                  fillDimensionSMXY(result, ratio, Math.min(originalWidth, 807));
              } break;
              case O: {
                  fillDimensionOPQ(result, ratio, Math.min(originalWidth, 130));
              } break;
              case P: {
                  fillDimensionOPQ(result, ratio, Math.min(originalWidth, 200));
              } break;
              case Q: {
                  fillDimensionOPQ(result, ratio, Math.min(originalWidth, 320));
              } break;
              case Z: {
                  fillDimensionZW(result, ratio, Math.min(originalWidth, 1280), Math.min(originalHeight, 1024));
              } break;
              case W: {
                  fillDimensionZW(result, ratio, Math.min(originalWidth, 2560), Math.min(originalHeight, 2048));
              } break;
          }
      }
  
      /*
       * Про S, M, X, Y известно, про копия обязательно пропорциональна, а ширина не должна превышать заданную.
       * Это значит, что для всех случаев(кроме тех, когда ширина картинки меньше указанной) соотношения
       * сторон картинка впишется пропорционально по ширине.
       */
      private static void fillDimensionSMXY(VKApiPhotoSize result, float ratio, int width) {
          result.width = width;
          result.height = (int) Math.ceil(result.width / ratio);
      }
  
      /*
       * Пропорциональная ширина. В принципе, все, что было сказано к предыдущему, верно и здесь,
       * за исключением того, что высота здесь не может превышать ширину * 1,5f
       */
      private static void fillDimensionOPQ(VKApiPhotoSize result, float ratio, int width) {
          fillDimensionSMXY(result, Math.min(1.5f, ratio), width);
      }
  
      /*
       * А здесь просто берем одну сторону за фактическую и исходя из нее вычисляем другую.
       */
      private static void fillDimensionZW(VKApiPhotoSize result, float ratio, int allowedWidth, int allowedHeight) {
          if(ratio > 1) { // ширина больше высоты
              result.width = allowedWidth;
              result.height = (int) (result.width / ratio);
          } else {
              result.height = allowedHeight;
              result.width = (int) (result.height * ratio);
          }
      }
  
      /**
       * Creates a dimension with explicit dimensions.
       * Can be helpful if the dimensions are exactly known.
       */
      public static VKApiPhotoSize create(String url, int width, int height) {
          VKApiPhotoSize result = new VKApiPhotoSize();
          result.src = url;
          result.width = width;
          result.height = height;
          float ratio = width / (float) height ;
          if(width <= 75) {
              result.type = S;
          } else if(width <= 130) {
              result.type = ratio <= 1.5f ? O : M;
          } else if(width <= 200 && ratio <= 1.5f) {
              result.type = P;
          } else if(width <= 320 && ratio <= 1.5f) {
              result.type = Q;
          } else if(width <= 604 ) {
              result.type = X;
          } else if(width <= 807) {
              result.type = Y;
          } else if(width <= 1280 && height <= 1024) {
              result.type = Z;
          } else if(width <= 2560 && height <= 2048) {
              result.type = W;
          }
          return result;
      }
  
      /**
       * Creates a dimension type and size of the original.
       */
      public static VKApiPhotoSize create(String url, char type, int originalWidth, int originalHeight) {
          VKApiPhotoSize result = new VKApiPhotoSize();
          result.src = url;
          result.type = type;
          fillDimensions(result, originalWidth, originalHeight);
          return result;
      }
  
      /**
       * Creates a square dimension type and size of the original.
       */
      public static VKApiPhotoSize create(String url, int dimension) {
          return create(url, dimension, dimension);
      }
  }