# encoding:utf-8
require 'open-uri'
require 'net/http'
require 'uri'
require 'json'
require 'digest/md5'
require 'digest/sha1'

require 'aliyun/oss'

module Ali

  class Oss
    BUCKET_NAME_PUBLIC_READ = CONFIG_FILE["ali_oss_bucket"] 
    URL_FOR_HOST = "#{CONFIG_FILE["ali_oss_bucket"]}.#{CONFIG_FILE["ali_oss_data_center"]}.aliyuncs.com"
    CDN_URL_FOR_HOST = URL_FOR_HOST

    @client = Aliyun::OSS::Client.new(
            :endpoint => "#{CONFIG_FILE["ali_oss_data_center"]}.aliyuncs.com",
            :access_key_id => CONFIG_FILE["ali_access_id"],
            :access_key_secret => CONFIG_FILE["ali_access_secret"])

    class << self

      def create_bucket(name, access = Aliyun::OSS::ACL::PUBLIC_READ)
        begin                  
          bucket = @client.create_bucket(name)          
          bucket.acl = access        
        rescue => e
          p e
        end
        return bucket
      end

      def get_bucket(name)        
        buckets = @client.list_buckets        
        buckets.each do |item|
          if item.name == name                  
            return item
          end
        end        
        return nil
      end

      def store(bucket_name, object_key, data)        
        bucket = self.get_bucket(bucket_name)        
        if bucket.blank?          
          bucket = self.create_bucket(bucket_name)          
        end        
        bucket.put_object(object_key){ |stream| stream << data }        
      end 

      def object_exist?(bucket_name, object_key)
        bucket = self.get_bucket(bucket_name)
        if not bucket.blank?
          objects = bucket.list_objects
          objects.each do |obj|
            if obj.key == object_key
              return true
            end 
          end
          return false   
        else
          raise "Bucket is not found with name: #{bucket_name}"
        end
      end      

      def delete_object(bucket_name, object_key)
        bucket = self.get_bucket(bucket_name)
        if not bucket.blank?
          begin
            bucket.delete_object(object_key)  
          rescue Exception => e
            p e
          end          
        else
          raise "Bucket is not found with name: #{bucket_name}"
        end
      end

    end
  end


  class Css
    #    attr_reader :version, :host
    #    attr_accessor :client_id, :secret_key

    ACCESS_KEY_ID = "HNPD1U7r1eWPzB82"
    SECRET_ACCESS_KEY = "yhmPqp3jBndWf8D9b5p40BRyNyqYG6"
    #内网
    #    HOST = "http://intranet.opensearch-cn-hangzhou.aliyuncs.com"
    #外网
    HOST = {
      "production" => "http://opensearch-cn-hangzhou.aliyuncs.com",
      "development" => "http://opensearch-cn-qingdao.aliyuncs.com"
    }

    class << self

      #根据参数创建签名信息
      def _signature(params, method)
        _params = {}
        params.each do |k,v|
          _params[k.to_s] = v
        end
        _params = _params.sort
        data = []
        _params.each do |p|
          next if p[1].size <= 0
          # p "before encode:#{p[1]}" if p[0] == "items"
          _p = URI.encode_www_form_component(p[1])
          _p = _p.gsub("+","%20").gsub("*","%2A").gsub("%7E","~")
          # p "after encode:#{_p}" if p[0] == "items"
          data << "#{URI.encode_www_form_component(p[0])}=#{_p}"
        end
        data = URI.encode_www_form_component(data.join("&"))
        data = [method.upcase, URI.encode_www_form_component("/"), data].join("&")
        # p "stringtosign=#{data}"
        data = data.gsub("%7E","~")
        signature = Base64::encode64(HMAC::SHA1.digest("#{SECRET_ACCESS_KEY}&", data))
        # p "signature=#{signature[0..-2]}"
        return signature[0..-2]
      end

      def _api_call(url, method = 'GET', params = {})
        begin
          params['Version'] = "v2"
          params['AccessKeyId'] = ACCESS_KEY_ID
          params['SignatureMethod'] = "HMAC-SHA1"
          t = Time.now.to_i - 8*3600
          params['Timestamp'] =  "#{Time.at(t).strftime("%Y-%m-%dT%H:%M:%SZ")}"
          params['SignatureVersion'] = "1.0"
          params['SignatureNonce'] = "#{Time.now.to_i}#{'%04d'%rand(9999)}"
          params['Signature'] = _signature(params, method)
          url = self::HOST[Rails.env] + url
          if method.upcase == 'GET'
            response = RestClient.get url, {:params => params}
          else
            response = RestClient.post url, params
          end
          return JSON.parse(response.body)
        rescue => e
          p e
        end
      end

      def list_index()
        uri = "/index"
        _api_call(uri, "get",{})
      end

      def create_index(index_name, template = "xikego_product")
        uri = "/index/#{index_name}"
        _api_call(uri, "post", {:action => "create", :template => template})
      end

      def delete_index(index_name)
        uri = "/index/#{index_name}"
        _api_call(uri, "post",{:action => "delete"})
      end

      def show_index(index_name)
        uri = "/index/#{index_name}"
        _api_call(uri, "get",{:action => "status"})
      end

      #items是个数组
      def create_doc(index_name, table_name, fields)
        uri = "/index/doc/#{index_name}"
        # t = (Time.now.to_i - 8*3600)*1000
        # items = [{"cmd" => "add", "timestamp" => t, "fields" => fields}]
        items = [{"cmd" => "add",  "fields" => fields}]
        items = items.to_json
        ret = _api_call(uri, "post",{"action" => "push", "table_name" =>  table_name, "items" => items})
        return ret
      end

      def delete_doc(index_name, table_name, id)
        uri = "/index/doc/#{index_name}"
        items = [{"cmd" => "delete", "fields" => {"id" => id.to_s}}]
        items = items.to_json
        _api_call(uri, "post",{"action" => "push", "table_name" =>  table_name, "items" => items})
      end

      def update_doc(index_name, table_name, fields)
        uri = "/index/doc/#{index_name}"
        # t = (Time.now.to_i - 8*3600)*1000
        # items = [{"cmd" => "update", "timestamp" => t, "fields" => fields}]
        items = [{"cmd" => "update", "fields" => fields}]
        items = items.to_json
        _api_call(uri, "post",{"action" => "push","table_name" =>  table_name,  "items" => items})
      end

      def search_doc(index_names, query)
        if index_names.class == Array
          index_name = index_names.join(";")
        else index_names.class == String
          index_name = index_names
        end
        uri = "/search"
        _api_call(uri,"get",{:query => query, :index_name => index_name, :summary_field => "title" })
      end

    end
  end


end

if __FILE__ == $0

end
