require "derelict"
require "fileutils"
require "json"
module Vagrantomatic
  class Instance
    VAGRANTFILE         = "Vagrantfile"
    VAGRANTFILE_JSON    = "#{VAGRANTFILE}.json"
    # We ship our own Vagrantfile with all variables externalised inside this
    # gem and get it into position by symlinking B-)
    MASTER_VAGRANTFILE  = File.join(File.dirname(File.expand_path(__FILE__)), "../../res/#{VAGRANTFILE}")

    CMD_DEFAULT = "sudo -i"
    CMD_WINDOWS = "cmd /c"

    def config
      @config
    end

    def windows
      @windows
    end

    # ruby convention is to use `config=` but this doesn't work properly inside
    # a constructor, it declarates a local variable `config`.  Calling from
    # outside the constructor works fine...
    def set_config(config)
      @config = config
      validate_config
    end

    def validate_config(fatal = true)
      valid = true
      if ! @config.has_key?("box")
        valid = false
        if fatal
          raise "Node #{@name} must specify box"
        end
      end

      valid
    end

    # Add a new folder to @config in the correct place.  Folders must be
    # specified as colon delimited strings: `HOST_PATH:VM_PATH`, eg
    # `/home/geoff:/stuff` would mount `/home/geoff` from the main computer and
    # would mount it inside the VM at /stuff.  Vagrant expects the `HOST_PATH`
    # to be an absolute path, however, you may specify a relative path here and
    # vagrantomatic will attempt to extract a fully qualified path by prepending
    # the present working directory.  If this is incorrect its up to the
    # programmer to fix this by passing in a fully qualified path in the first
    # place
    def add_shared_folder(folders)
      folders=Array(folders)
      # can't use dig() might not be ruby 2.3
      if ! @config.has_key?("folders")
        @config["folders"] = []
      end

      # all paths must be fully qualified.  If we were asked to do a relative path, change
      # it to the current directory since that's probably what the user wanted.  Not right?
      # user supply correct path!
      folders.each { |folder|
        if ! folder.start_with? '/'
          folder = "#{Dir.pwd}/#{folder}"
        end

        @config["folders"] << folder
      }
    end

    def initialize(vagrant_vm_dir, name, logger:nil, config:nil)
      @name           = name
      @vagrant_vm_dir = vagrant_vm_dir
      @logger         = Logger.new(logger).logger

      # (attempt) to auto-detect windows based on the VM name containing 'win'
      # allow users to override this with config[windows]=true
      @windows = ((/win/i === @name)  or (@config.has_key?('windows') and config['windows'] == true))

      # if we encounter conditions such as missing or damaged files we may need
      # to force a save that would normally not be detected - eg if we load bad
      # json it gets fixed up to an empty hash which would them be compared to a
      # fresh read of the file (also results in empty hash) - so we must supply
      # another way to force the save here
      @force_save     = false

      # use supplied config if present, otherwise load from file
      if config
        # validate a user-supplied config now, at the point of insertion
        # by this point we have a config either from file or supplied by user it
        # must be valid for us to proceed!
        set_config(config)
      else

        # this passed-in config could still be bad - we will validate it before
        # use on either save() or get_vm().  We DONT validate it right away
        # because this would cause the constructor to explode when we are trying
        # to introspec intances - we would never be able to fix anything
        # automatically
        @config = configfile_hash
      end

      @logger.debug "initialized vagrantomatic instance for #{name}"
    end

    def vm_instance_dir
      File.join(@vagrant_vm_dir, @name)
    end

    def vagrantfile
      File.join(vm_instance_dir, VAGRANTFILE)
    end

    def configfile
      File.join(vm_instance_dir, VAGRANTFILE_JSON)
    end

    # return a hash of the configfile or empty hash if error encountered
    def configfile_hash

      config  = {}
      begin
        json    = File.read(configfile)
        config  = JSON.parse(json)
      rescue Errno::ENOENT
        # depending on whether the instance has been saved or not, we may not
        # yet have a configfile - allow to proceed
        @logger.debug "#{configfile} does not exist"
        @force_save = true
      rescue JSON::ParserError
        # swallow parse errors so that we can destroy and recreate automatically
        @logger.debug "JSON parse error in #{configfile}"
        @force_save = true
      end
      config
    end

    def configured?
      configured = true

      if ! Dir.exists? (vm_instance_dir)
        @logger.debug "Vagrant instance directory #{vm_instance_dir} does not exist"
        configured = false
      end

      if ! File.exists?(vagrantfile)
        @logger.debug "#{VAGRANTFILE} not found at #{vagrantfile}"
        configured = false
      end

      if ! File.exists?(configfile)
        @logger.debug "#{VAGRANTFILE_JSON} not found at #{configfile}"
        configured = false
      end

      # check config hash is valid without causing a fatal error if its damaged
      if ! validate_config(false)
        configured = false
      end

      configured
    end

    def save
      @logger.debug("validating settings for save...")
      validate_config
      @logger.debug("saving vm settings...")
      FileUtils.mkdir_p(vm_instance_dir)
      ensure_config
      ensure_vagrantfile

      @force_save = false
    end

    # Vagrant to be driven from a .json config file, all
    # the parameters are externalised here
    def ensure_config
      if ! in_sync?
        File.open(configfile,"w") do |f|
          f.write(@config.to_json)
        end
      end
    end

    # The Vagrantfile itself is shipped as part of this
    # module and delivered via pluginsync, so we just need
    # to symlink it for each directory.  This gives us the
    # benefit being to update by dropping a new module too
    def ensure_vagrantfile
      FileUtils.ln_sf(MASTER_VAGRANTFILE, vagrantfile)
    end

    def get_vm
      # Create an instance (represents a Vagrant **installation**)
      if ! in_sync?
        raise "get_vm called for instance #{@name} but it is not in_sync! (call save() first?)"
      end

      validate_config

      vagrant_installation = Derelict.instance(Vagrantomatic::DEFAULT_VAGRANT_DIR)
      result = vagrant_installation.execute('--version') # Derelict::Executer object (vagrant --version)
      if result.success?
        # vagrant present and working, connect to our vm INSTANCE
        vm = vagrant_installation.connect(vm_instance_dir)
      else
        raise "Error connecting to vagrant! (vagrant --version failed)"
      end

      vm
    end

    def execute_and_log(op, *args)
      get_vm.execute(op, args) { |stdout, stderr|
        # only one of these will ever be set at a time, other one is nil
        @logger.debug "#{stdout}#{stderr}".strip
      }.success?
    end

    def in_sync?
      configured  = false
      have_config = configfile_hash
      if (! @force_save) and (have_config == @config )
        configured = true
      end

      configured
    end

    def start
      execute_and_log(:up)
    end

    def stop
      execute_and_log(:suspend)
    end

    def purge
      execute_and_log(:destroy, '-f')
      if Dir.exists? vm_instance_dir
        FileUtils::rm_rf(vm_instance_dir)
      end
    end

    def reload
      execute_and_log(:reload)
    end

    def reset
      execute_and_log(:destroy, '-f')
      execute_and_log(:up)
    end

    def run(command)
      # arrayify and wrap with correct command for windows vs linux
      command = ["#{@windows ? CMD_WINDOWS : CMD_DEFAULT} #{command}"]
      command.unshift("-c")

      messages = []
      vm = get_vm
      # throw the command over the wall to derelect whatever the state of instance
      # using the appropriate subcommand
      runner = @windows ? :winrm : :ssh
      executor = vm.execute(runner, command) { |stdout,stderr|
        line = "#{stdout}#{stderr}".strip
        @logger.debug line
        messages << line
      }
      @logger.info("command '#{command}' resulted in #{messages.size} lines (exit status: #{executor.status})")
      return executor.status, messages
    end

  end
end


module Ropenstack
  ##
  # * Name: ObjectStorage
  # * Description: Implementation of the Block Storage API Client in Ruby.
  # * Author: Sam 'Tehsmash' Betts
  # * Date: 01/15/2013
  ##
  class ObjectStorage < OpenstackService
    ## Accounts
    def account(id, head)
      if head
        get_request(address(id), @token)
      else
        head_request(address(id), @token)
      end
    end

    def create_account()
    end

    ## Containers
    def container(account, container, head)
      if head
        get_request(address(account + "/" + container), @token)
      else
        head_request(address(account + "/" + container), @token)
      end
    end

    def create_container(account, container)
    end

    def delete_container(account, container)
    end

    def update_container(account, container)
    end

    ## Objects
    def object(account, container, object)
      get_request(address(account + "/" + container + "/" + object), @token)
    end

    def object_metadata(account, container, object)
      head_request(address(account + "/" + container + "/" + object), @token)
    end

    def create_object(account, container, object)
    end

    def copy_object(account, container, object)
    end

    def delete_object(account, container, object)
    end

    def create_object_metadata(account, container, object)
    end
  end
end


# -*- encoding: utf-8 -*-
require 'multi_json' unless defined?(::MultiJson)
require 'active_support/core_ext/string' unless ::String.respond_to?(:present?)
require 'active_support/core_ext/object/inclusion' unless ::String.respond_to?(:in?)

module SimpleFormat
  class Emoji
    def initialize(mapping=nil)
      mapping ||= begin
        emoji_json = File.read(File.absolute_path(File.dirname(__FILE__) + '/../../config/index.json'))
        MultiJson.load(emoji_json, symbolize_keys: true)
      end

      @emoji_by_name = {}
      @emoji_by_unicode = {}

      mapping.each do |emoji_hash|
        name = emoji_hash[:name]
        @emoji_by_name[name] = emoji_hash if name

        unicode = emoji_hash[:unicode]
        @emoji_by_unicode[unicode] = emoji_hash if unicode
      end

      @emoji_name_regex = /:([a-z0-9\+\-_]+):/
      @emoji_unicode_regex = /#{@emoji_by_unicode.keys.join('|')}/
    end

    # 主机地址
    def asset_host
      @asset_host || 'emoji.qiniudn.com'
    end
    # 设置主机地址
    def asset_host=(host)
      @asset_host = host
    end
    # 资源路径
    def asset_path
      @asset_path || '/'
    end
    # 设置路径
    def asset_path=(path)
      @asset_path = path
    end
    # 图标尺寸
    def asset_size
      @asset_size || ''
    end
    # 设置图标尺寸
    def asset_size=(size)
      @asset_size = size
    end
    # 分隔符
    def asset_delimiter
      @asset_delimiter || '_'
    end
    def asset_delimiter=(delimiter)
      @asset_delimiter = delimiter
    end
    # 通过（名称、字符）替换表情
    def replace_emoji_with_images(string)
      return string unless string
      html ||= string.dup
      html = replace_name_with_images(html)
      html = replace_unicode_with_images(html.to_str)
      return html
    end
    # 通过（名称）替换表情
    def replace_name_with_images(string)
      unless string && string.match(names_regex)
        return string
      end

      string.to_str.gsub(names_regex) do |match|
        if names.include?($1)
          %Q{}
        else
          match
        end
      end
    end
    # 通过（字符）替换表情
    def replace_unicode_with_images(string)
      unless string && string.match(unicodes_regex)
        return string
      end

      html ||= string.dup
      html.gsub!(unicodes_regex) do |unicode|
        %Q{}
      end
    end
    # 通过（名称）合成图片地址
    def image_url_for_name(name)
      image_url = "#{asset_host}#{ File.join(asset_path, name) }.png"
      if image_url.present?
        if asset_size.present? && asset_size.in?(sizes)
          image_url = [image_url, asset_size].join(asset_delimiter)
        end
      end
      return image_url
    end
    # 通过（字符）合成图片地址
    def image_url_for_unicode(unicode)
      emoji = find_by_unicode(unicode)
      image_url_for_name(emoji[:name]) unless emoji.nil?
    end
    # 通过（字符）找表情
    def find_by_unicode(moji)
      @emoji_by_unicode[moji]
    end
    # 通过（名称）表情
    def find_by_name(name)
      @emoji_by_name[name]
    end
    # 名称列表
    def names
      @emoji_by_name.keys
    end
    # 字符列表
    def unicodes
      @emoji_by_unicode.keys
    end
    # 名称匹配表达式
    def names_regex
      @emoji_name_regex
    end
    # 字符匹配表达式
    def unicodes_regex
      @emoji_unicode_regex
    end

    private

    # 尺寸
    def sizes
      %W(16x16 24x24 32x32 48x48 56x56)
    end
  end
end


# An identity map that tracks data that's been loaded, and data that we still need to load.
# As tables are loaded and processed, the identity map will keep a list of child models that have been "seen" and will need to be loaded for the final view.
# The identity map defines a scope for the associated queries.
# The scope can be thought of as a set of named filters.
module Praxis::Mapper
  class IdentityMap
    include IdentityMapExtensions::Persistence

    class UnloadedRecordException < StandardError; end;
    class UnsupportedModel < StandardError; end;
    class UnknownIdentity < StandardError; end;

    attr_reader :unloaded
    attr_reader :queries
    attr_reader :blueprint_cache

    attr_accessor :scope

    class << self
      attr_accessor :config
    end

    # Stores given identity map in a thread-local variable
    # @param [IdentityMap] some identity map
    def self.current=(identity_map)
      Thread.current[:_praxis_mapper_identity_map] = identity_map
    end

    # @return [IdentityMap] current identity map from thread-local variable
    def self.current
      map = Thread.current[:_praxis_mapper_identity_map]
      raise "current IdentityMap not set" unless map
      map
    end

    # @return [Boolean] whether identity map thread-local variable has been set
    def self.current?
      Thread.current.key?(:_praxis_mapper_identity_map) && Thread.current[:_praxis_mapper_identity_map].kind_of?(Praxis::Mapper::IdentityMap)
    end

    def clear?
      @rows.empty? &&
        @staged.empty? &&
        @row_keys.empty? &&
        @queries.empty?
    end

    # TODO: how come scope can be set from 3 different methods?
    #
    # @param scope [Hash] a set of named filters to apply in query
    # @example {:account => [:account_id, 71], :user => [:user_id, 2]}
    #
    def self.setup!(scope={})
      if self.current?
        if !self.current.clear?
          raise "Denied for a pre-existing condition: Identity map has been used."
        else
          self.current.scope = scope
          return self.current
        end
      else
        self.current = self.new(scope)
      end
    end

    # TODO: support multiple connections
    def initialize(scope={})
      @connection_manager = ConnectionManager.new
      @scope = scope
      @selector_generator = Praxis::Mapper::SelectorGenerator.new
      clear!
    end

    def selectors
      @selector_generator.selectors
    end

    def clear!
      @rows = Hash.new { |h,k| h[k] = Array.new }

      # for ex:
      #   @staged[Instance][:id] = Set.new
      # yields:
      #  {Instance => {:id => Set.new(1,2,3), :name => Set.new("George Jr.") } }
      @staged = Hash.new do |hash,model|
        hash[model] = Hash.new do |identity_hash, identity_name|
          identity_hash[identity_name] = Set.new
        end
      end

      # for ex:
      #   @row_keys["instances"][:id][1] = Object.new
      # yields:
      #   {"instances"=>{:id=>{1=>Object.new}}
      @row_keys = Hash.new do |row_hash,model|
        row_hash[model] = Hash.new do |primary_keys, key_name|
          primary_keys[key_name] = Hash.new
        end
      end

      @queries = Hash.new { |h,k| h[k] = Set.new }

      # see how it feels to store blueprints here
      # for ex:
      #   @blueprints[User][some_object] = User.new(some_object)
      @blueprint_cache = Hash.new do |cache,blueprint_class|
        cache[blueprint_class] = Hash.new
      end

      # TODO: rework this so it's a hash with default values and simplify #index
      @secondary_indexes = Hash.new do |hash, model|
        hash[model] = Hash.new
      end
    end

    def load(model, &block)
      raise "Can't load unfinalized model #{model}" unless model.finalized?

      query_class = @connection_manager.repository(model.repository_name)[:query]
      query = query_class.new(self, model, &block)

      if query.where == :staged
        query.where = nil
        return finalize_model!(model, query)
      end

      ActiveSupport::Notifications.instrument 'praxis.mapper.load', model: model do
        records = query.execute
        im_records = add_records(records)

        # TODO: refactor this to better-hide queries?
        query.freeze
        queries[model].add(query)

        subload(model, query, records)

        im_records
      end
    end

    def stage_for!(spec, records)
      case spec[:type]
      when :many_to_one
        stage_many_to_one(spec, records)
      when :array_to_many
        stage_array_to_many(spec, records)
      when :one_to_many
        stage_one_to_many(spec, records)
      when :many_to_array
        stage_many_to_array(spec, records)
      end
    end

    def subload(model, query, records)
      query.load.each do |(association_name, block)|
        spec = model.associations.fetch(association_name)

        associated_model = spec[:model]

        key, values = stage_for!(spec, records)

        existing_records = []
        values.reject! do |value|
          if @row_keys[associated_model].has_key?(key) &&
              @row_keys[associated_model][key].has_key?(value)
            existing_records << @row_keys[associated_model][key][value]
          else
            false
          end
        end

        new_query_class = @connection_manager.repository(associated_model.repository_name)[:query]
        new_query = new_query_class.new(self,associated_model, &block)

        new_records = new_query.multi_get(key, values)

        self.queries[associated_model].add(new_query)

        add_records(new_records)

        subload(associated_model, new_query, new_records + existing_records)
      end
    end

    # Last parameter in array can be a hash of objects
    # It is implemented this way (instead of (*models, instrument: true)) because when passing in
    # Sequel models, ruby will invoke the ".to_hash" on them, causing a "load" when trying to restructure the args
    def finalize!(*models_and_opts)

      models, instrument = if models_and_opts.last.kind_of?(::Hash)
        ins = models_and_opts.last.fetch(:instrument) do
          true
        end
        [ models_and_opts[0..-2], ins ]
      else
        [ models_and_opts, true ]
      end

      if instrument
        ActiveSupport::Notifications.instrument 'praxis.mapper.finalize' do
          _finalize!(*models)
        end
      else
        _finalize!(*models)
      end
    end

    def _finalize!(*models)
      models = @staged.keys if models.empty?

      did_something = models.any? do |model|
        finalize_model!(model).any?
      end

      if did_something
        _finalize!
      else
        release
      end
    end

    def release
      @connection_manager.release
    end

    # don't doc. never ever use yourself!
    # FIXME: make private and fix specs that break?
    def finalize_model!(model, query = nil)
      staged_queries = @staged[model].delete(:_queries) || []
      staged_keys = @staged[model].keys
      non_identities = staged_keys - model.identities

      results = Set.new

      return results if @staged[model].all? { |(_key, values)| values.empty? }

      if query.nil?
        query_class = @connection_manager.repository(model.repository_name)[:query]
        query = query_class.new(self, model)
      end

      # Apply any relevant blocks passed to track in the original queries
      staged_queries.each do |staged_query|
        staged_query.track.each do |(association_name, block)|
          next unless block

          spec = staged_query.model.associations[association_name]

          if spec[:model] == model
            query.instance_eval(&block)
            if (spec[:type] == :many_to_one || spec[:type] == :array_to_many) && query.where
              file, line = block.source_location
              trace = ["#{file}:#{line}"] | caller
              raise RuntimeError, "Error finalizing model #{model.name} for association #{association_name.inspect} -- using a where clause when tracking associations of type #{spec[:type].inspect} is not supported", trace
            end
          end
        end
      end

      # process non-unique staged keys
      #   select identity (any one should do) for those keys and stage blindly
      #   load and add records.

      if non_identities.any?
        to_stage = Hash.new do |hash,identity|
          hash[identity] = Set.new
        end

        non_identities.each do |key|
          values = @staged[model].delete(key)

          rows = query.multi_get(key, values, select: model.identities, raw: true)
          rows.each do |row|
            model.identities.each do |identity|
              if identity.kind_of? Array
                to_stage[identity] << row.values_at(*identity)
              else
                to_stage[identity] << row[identity]
              end
            end
          end
        end

        self.stage(model, to_stage)
      end

      model.identities.each do |identity_name|
        values = self.get_staged(model,identity_name)
        next if values.empty?

        query.where = nil # clear out any where clause from non-identity
        records = query.multi_get(identity_name, values)

        # TODO: refactor this to better-hide queries?
        self.queries[model].add(query)

        results.merge(add_records(records))

        # add nil records for records that were not found by the multi_get
        missing_keys = self.get_staged(model,identity_name)
        missing_keys.each do |missing_key|
          @row_keys[model][identity_name][missing_key] = nil
          get_staged(model, identity_name).delete(missing_key)
        end

      end

      query.freeze

      # TODO: check whether really really did get all the records we should have....
      results.to_a
    end

    def row_by_key(model,key, value)
      @row_keys[model][key].fetch(value) do
        raise UnloadedRecordException, "Did not load #{model} with #{key} = #{value.inspect}."
      end
    end

    def rows_for(model)
      @rows[model]
    end

    def index(model, key, value)
      unless @secondary_indexes[model].has_key? key
        @secondary_indexes[model][key] ||= Hash.new
        reindex!(model, key)
      end

      @secondary_indexes[model][key][value] ||= Array.new
    end

    def reindex!(model, key)
      rows_for(model).each do |row|
        val = if key.kind_of? Array
          key.collect { |k| row.send(k) }
        else
          row.send(key)
        end
        # FIXME: make this a set? or handle duplicates better
        index(model, key, val) << row
      end
    end

    def all(model,conditions={})
      return rows_for(model) if conditions.empty?

      key, values = conditions.first

      # optimize the common case of a single value
      if values.size == 1
        value = values[0]
        if @row_keys[model].has_key?(key)
          res = @row_keys[model][key][value]

          if res
            [res]
          else
            []
          end
        else
          index(model, key, value)
        end
      else
        if @row_keys[model].has_key?(key)
          values.collect do |v|
            @row_keys[model][key][v]
          end.compact
        else
          values.each_with_object(Array.new) do |v, results|
            results.push(*index(model, key, v))
          end
        end
      end
    end

    def get(model,condition)
      key, value = condition.first

      row_by_key(model, key, value)
    end

    def get_staged(model, key)
      @staged[model][key]
    end

    def stage(model, data)
      data.each do |key, values|
        unless values.kind_of? Enumerable
          values = [values]
        end

        # ignore rows we have already loaded... add sanity checking?
        if model.identities.include?(key)
          values.reject! { |k| @row_keys[model][key].has_key? k }
        end

        get_staged(model,key).merge(values)
      end
    end

    def connection(name)
      @connection_manager.checkout(name)
    end

    def extract_keys(field, records)
      row_keys = Set.new
      if field.kind_of?(Array) # composite identities
        records.each do |record|
          row_key = field.collect { |col| record.send(col) }
          row_keys << row_key unless row_key.include?(nil)
        end
      else
        row_keys.merge records.collect(&field).compact
      end
      row_keys
    end

    def stage_many_to_one(tracked_association, records)
      key = tracked_association[:key]
      primary_key = tracked_association[:primary_key] || :id

      row_keys = extract_keys(key, records)

      [primary_key, row_keys]
    end

    def stage_one_to_many(tracked_association, records)
      key = tracked_association[:key]
      primary_key = tracked_association[:primary_key] || :id

      row_keys = extract_keys(primary_key, records)

      [key, row_keys]
    end

    def stage_array_to_many(tracked_association, records)
      key = tracked_association[:key]
      primary_key = tracked_association[:primary_key] || :id

      row_keys = Set.new
      records.collect(&key).each do |keys|
        row_keys.merge keys
      end

      row_keys.reject! do |row_key|
        row_key.nil? || (row_key.kind_of?(Array) && row_key.include?(nil))
      end

      [primary_key, row_keys]
    end

    def stage_many_to_array(tracked_association, records)
      raise "not supported yet"
    end

    def add_records(records)
      return [] if records.empty?

      to_stage = Hash.new do |hash,staged_model|
        hash[staged_model] = Hash.new do |identities, identity_name|
          identities[identity_name] = Set.new
        end
      end

      tracked_associations = if (query = records.first._query)
        query.tracked_associations.each do |tracked_association|
          associated_model = tracked_association[:model]
          to_stage[associated_model][:_queries] << query
        end
      else
        []
      end

      tracked_associations.each do |tracked_association|
        associated_model = tracked_association[:model]

        association_key, row_keys = stage_for!(tracked_association, records)
        row_keys.each do |row_key|
          to_stage[associated_model][association_key].add(row_key)
        end

      end

      im_records = records.collect do |record|
        add_record(record)
      end

      to_stage.each do |model_to_stage, data|
        stage(model_to_stage, data)
      end

      im_records
    end

    # return the record provided (if added to the identity map)
    # or return the corresponding record if it was already present
    def add_record(record)
      model = record.class
      record.identities.each do |identity, key|
        # FIXME: Should we be overwriting (possibly) a "nil" value from before?
        #        (due to that row not being found by a previous query)
        #        (That'd be odd since that means we tried to load that same identity)
        if (existing = @row_keys[model][identity][key])
          # FIXME: should merge record into existing to add any additional fields
          return existing
        end

        get_staged(model, identity).delete(key)
        @row_keys[model][identity][key] = record
      end

      @secondary_indexes[model].each do |key, indexed_values|
        val = if key.kind_of? Array
          key.collect { |k| record.send(k) }
        else
          record.send(key)
        end

        indexed_values[val] << record
      end

      record.identity_map = self
      @rows[model] << record
      record
    end

    alias_method :<<, :add_record

    def query_statistics
      QueryStatistics.new(queries)
    end

    def add_selectors(resource, fields)
      @selector_generator.add(resource, fields)
    end

  end
end


# -*- encoding: utf-8 -*-

module SimpleFormat
  class AutoLink

    def initialize()
      @regex = {
            protocol: %r{(?: ((?:ed2k|ftp|http|https|irc|mailto|news|gopher|nntp|telnet|webcal|xmpp|callto|feed|svn|urn|aim|rsync|tag|ssh|sftp|rtsp|afs|file):)// | www\. )[^\s<]+}x,
                href: [/<[^>]+$/, /^[^>]*>/, //i, /<\/a>/i],
                mail: /[\w.!#\$%+-]+@[\w-]+(?:\.[\w-]+)+/,
            brackets: { ']' => '[', ')' => '(', '}' => '{' },
        word_pattern: RUBY_VERSION < '1.9' ? '\w' : '\p{Word}'
      }
    end

    def all(text)
      return text unless text
      email_addresses( urls(text) )
    end

    # Turns all urls into clickable links.  If a block is given, each url
    # is yielded and the result is used as the link text.
    def urls(text)

      text.gsub(@regex[:protocol]) do
        scheme, href = $1, $&
        punctuation = []

        if auto_linked?($`, $')
          # do not change string; URL is already linked
          href
        else
          # don't include trailing punctuation character as part of the URL
          while href.sub!(/[^#{@regex[:word_pattern]}\/-]$/, '')
            punctuation.push $&
            if opening = @regex[:brackets][punctuation.last] and href.scan(opening).size > href.scan(punctuation.last).size
              href << punctuation.pop
              break
            end
          end

          link_text = block_given?? yield(href) : href
          href = '//' + href unless scheme

          "#{link_text}" + punctuation.reverse.join('')
        end
      end
    end

    # Turns all email addresses into clickable links.  If a block is given,
    # each email is yielded and the result is used as the link text.
    def email_addresses(text)
      text.gsub(@regex[:mail]) do
        text = $&
        if auto_linked?($`, $')
          text
        else
          display_text = (block_given?) ? yield(text) : text
          # mail_to text, display_text
          "#{display_text}"
        end
      end
    end

    private

    # Detects already linked context or position in the middle of a tag
    def auto_linked?(left, right)
      (left =~ @regex[:href][0] and right =~ @regex[:href][1]) or (left.rindex(@regex[:href][2]) and $' !~ @regex[:href][3])
    end
  end
end


# Taken from Rails

# encoding: utf-8
require 'singleton'

module Risky::Inflector
  extend self

  # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
  # inflection rules. Examples:
  #
  #   ActiveSupport::Inflector.inflections do |inflect|
  #     inflect.plural /^(ox)$/i, '\1\2en'
  #     inflect.singular /^(ox)en/i, '\1'
  #
  #     inflect.irregular 'octopus', 'octopi'
  #
  #     inflect.uncountable "equipment"
  #   end
  #
  # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
  # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
  # already have been loaded.
  class Inflections
    include Singleton

    attr_reader :plurals, :singulars, :uncountables, :humans

    def initialize
      @plurals, @singulars, @uncountables, @humans = [], [], [], []
    end

    # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
    # The replacement should always be a string that may include references to the matched data from the rule.
    def plural(rule, replacement)
      @uncountables.delete(rule) if rule.is_a?(String)
      @uncountables.delete(replacement)
      @plurals.insert(0, [rule, replacement])
    end

    # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
    # The replacement should always be a string that may include references to the matched data from the rule.
    def singular(rule, replacement)
      @uncountables.delete(rule) if rule.is_a?(String)
      @uncountables.delete(replacement)
      @singulars.insert(0, [rule, replacement])
    end

    # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
    # for strings, not regular expressions. You simply pass the irregular in singular and plural form.
    #
    # Examples:
    #   irregular 'octopus', 'octopi'
    #   irregular 'person', 'people'
    def irregular(singular, plural)
      @uncountables.delete(singular)
      @uncountables.delete(plural)
      if singular[0,1].upcase == plural[0,1].upcase
        plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
        singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
      else
        plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
        plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
        singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1])
        singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1])
      end
    end

    # Add uncountable words that shouldn't be attempted inflected.
    #
    # Examples:
    #   uncountable "money"
    #   uncountable "money", "information"
    #   uncountable %w( money information rice )
    def uncountable(*words)
      (@uncountables << words).flatten!
    end

    # Specifies a humanized form of a string by a regular expression rule or by a string mapping.
    # When using a regular expression based replacement, the normal humanize formatting is called after the replacement.
    # When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name')
    #
    # Examples:
    #   human /_cnt$/i, '\1_count'
    #   human "legacy_col_person_name", "Name"
    def human(rule, replacement)
      @humans.insert(0, [rule, replacement])
    end

    # Clears the loaded inflections within a given scope (default is <tt>:all</tt>).
    # Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>,
    # <tt>:singulars</tt>, <tt>:uncountables</tt>, <tt>:humans</tt>.
    #
    # Examples:
    #   clear :all
    #   clear :plurals
    def clear(scope = :all)
      case scope
        when :all
          @plurals, @singulars, @uncountables = [], [], []
        else
          instance_variable_set "@#{scope}", []
      end
    end
  end

  # Yields a singleton instance of Inflector::Inflections so you can specify additional
  # inflector rules.
  #
  # Example:
  #   ActiveSupport::Inflector.inflections do |inflect|
  #     inflect.uncountable "rails"
  #   end
  def inflections
    if block_given?
      yield Inflections.instance
    else
      Inflections.instance
    end
  end

  # Returns the plural form of the word in the string.
  #
  # Examples:
  #   "post".pluralize             # => "posts"
  #   "octopus".pluralize          # => "octopi"
  #   "sheep".pluralize            # => "sheep"
  #   "words".pluralize            # => "words"
  #   "CamelOctopus".pluralize     # => "CamelOctopi"
  def pluralize(word)
    result = word.to_s.dup

    if word.empty? || inflections.uncountables.include?(result.downcase)
      result
    else
      inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
      result
    end
  end

  # The reverse of +pluralize+, returns the singular form of a word in a string.
  #
  # Examples:
  #   "posts".singularize            # => "post"
  #   "octopi".singularize           # => "octopus"
  #   "sheep".singluarize            # => "sheep"
  #   "word".singularize             # => "word"
  #   "CamelOctopi".singularize      # => "CamelOctopus"
  def singularize(word)
    result = word.to_s.dup

    if inflections.uncountables.any? { |inflection| result =~ /#{inflection}\Z/i }
      result
    else
      inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
      result
    end
  end

  # By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+
  # is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase.
  #
  # +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
  #
  # Examples:
  #   "active_record".camelize                # => "ActiveRecord"
  #   "active_record".camelize(:lower)        # => "activeRecord"
  #   "active_record/errors".camelize         # => "ActiveRecord::Errors"
  #   "active_record/errors".camelize(:lower) # => "activeRecord::Errors"
  def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
    if first_letter_in_uppercase
      lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
    else
      lower_case_and_underscored_word.first.downcase + camelize(lower_case_and_underscored_word)[1..-1]
    end
  end

  # Capitalizes all the words and replaces some characters in the string to create
  # a nicer looking title. +titleize+ is meant for creating pretty output. It is not
  # used in the Rails internals.
  #
  # +titleize+ is also aliased as as +titlecase+.
  #
  # Examples:
  #   "man from the boondocks".titleize # => "Man From The Boondocks"
  #   "x-men: the last stand".titleize  # => "X Men: The Last Stand"
  def titleize(word)
    humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize }
  end

  # The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string.
  #
  # Changes '::' to '/' to convert namespaces to paths.
  #
  # Examples:
  #   "ActiveRecord".underscore         # => "active_record"
  #   "ActiveRecord::Errors".underscore # => active_record/errors
  def underscore(camel_cased_word)
    camel_cased_word.to_s.gsub(/::/, '/').
      gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
      gsub(/([a-z\d])([A-Z])/,'\1_\2').
      tr("-", "_").
      downcase
  end

  # Replaces underscores with dashes in the string.
  #
  # Example:
  #   "puni_puni" # => "puni-puni"
  def dasherize(underscored_word)
    underscored_word.gsub(/_/, '-')
  end

  # Capitalizes the first word and turns underscores into spaces and strips a
  # trailing "_id", if any. Like +titleize+, this is meant for creating pretty output.
  #
  # Examples:
  #   "employee_salary" # => "Employee salary"
  #   "author_id"       # => "Author"
  def humanize(lower_case_and_underscored_word)
    result = lower_case_and_underscored_word.to_s.dup

    inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
    result.gsub(/_id$/, "").gsub(/_/, " ").capitalize
  end

  # Removes the module part from the expression in the string.
  #
  # Examples:
  #   "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections"
  #   "Inflections".demodulize                                       # => "Inflections"
  def demodulize(class_name_in_module)
    class_name_in_module.to_s.gsub(/^.*::/, '')
  end

  # Create the name of a table like Rails does for models to table names. This method
  # uses the +pluralize+ method on the last word in the string.
  #
  # Examples
  #   "RawScaledScorer".tableize # => "raw_scaled_scorers"
  #   "egg_and_ham".tableize     # => "egg_and_hams"
  #   "fancyCategory".tableize   # => "fancy_categories"
  def tableize(class_name)
    pluralize(underscore(class_name))
  end

  # Create a class name from a plural table name like Rails does for table names to models.
  # Note that this returns a string and not a Class. (To convert to an actual class
  # follow +classify+ with +constantize+.)
  #
  # Examples:
  #   "egg_and_hams".classify # => "EggAndHam"
  #   "posts".classify        # => "Post"
  #
  # Singular names are not handled correctly:
  #   "business".classify     # => "Busines"
  def classify(table_name)
    # strip out any leading schema name
    camelize(singularize(table_name.to_s.sub(/.*\./, '')))
  end

  # Creates a foreign key name from a class name.
  # +separate_class_name_and_id_with_underscore+ sets whether
  # the method should put '_' between the name and 'id'.
  #
  # Examples:
  #   "Message".foreign_key        # => "message_id"
  #   "Message".foreign_key(false) # => "messageid"
  #   "Admin::Post".foreign_key    # => "post_id"
  def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
    underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id")
  end

  # Ruby 1.9 introduces an inherit argument for Module#const_get and
  # #const_defined? and changes their default behavior.
  if Module.method(:const_get).arity == 1
    # Tries to find a constant with the name specified in the argument string:
    #
    #   "Module".constantize     # => Module
    #   "Test::Unit".constantize # => Test::Unit
    #
    # The name is assumed to be the one of a top-level constant, no matter whether
    # it starts with "::" or not. No lexical context is taken into account:
    #
    #   C = 'outside'
    #   module M
    #     C = 'inside'
    #     C               # => 'inside'
    #     "C".constantize # => 'outside', same as ::C
    #   end
    #
    # NameError is raised when the name is not in CamelCase or the constant is
    # unknown.
    def constantize(camel_cased_word)
      names = camel_cased_word.split('::')
      names.shift if names.empty? || names.first.empty?

      constant = Object
      names.each do |name|
        constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
      end
      constant
    end
  else
    def constantize(camel_cased_word) #:nodoc:
      names = camel_cased_word.split('::')
      names.shift if names.empty? || names.first.empty?

      constant = Object
      names.each do |name|
        constant = constant.const_get(name, false) || constant.const_missing(name)
      end
      constant
    end
  end

  # Turns a number into an ordinal string used to denote the position in an
  # ordered sequence such as 1st, 2nd, 3rd, 4th.
  #
  # Examples:
  #   ordinalize(1)     # => "1st"
  #   ordinalize(2)     # => "2nd"
  #   ordinalize(1002)  # => "1002nd"
  #   ordinalize(1003)  # => "1003rd"
  def ordinalize(number)
    if (11..13).include?(number.to_i % 100)
      "#{number}th"
    else
      case number.to_i % 10
        when 1; "#{number}st"
        when 2; "#{number}nd"
        when 3; "#{number}rd"
        else    "#{number}th"
      end
    end
  end
end


require 'mutagem'
require 'erb'

module Revenc

  class BasicAction

    def initialize(name=nil, options={})
      raise ArgumentError, "Options should be a hash" unless options.is_a?(Hash)
      @name = name
      @options = options
    end

    def name
      @name
    end

    def name=(value)
      @name = value
    end

    def options
      @options ||= {}
    end

    def options=(value)
      @options = value
    end

    def errors
      @errors ||= Errors.new
    end

    def exists?
      false
    end

    def validate
    end

    def valid?
      errors.clear
      validate
      errors.empty?
    end

    def cmd
      return nil unless @cmd
      # process ERB
      render(@cmd)
    end

    def cmd=(value)
      @cmd = value
    end

  private

    def system_cmd(cmd=nil)
      raise "ERROR: cmd not given" unless cmd
      return true if options[:dry_run]
      system cmd
    end

    def render(value, b = binding)
      ERB.new(value).result(b)
    end

  end

  class FileSystemEntity < BasicAction

    # return fully qualified name
    def name
      return @name unless (@name && File.exists?(@name))
      File.expand_path(@name)
    end

    def exists?
      File.exists?(name) if name
    end

  end

  class TextFile < FileSystemEntity

    def empty?
      return true unless exists?

      contents = nil
      File.open(@name, "r") do |f|
        contents = f.read
      end
      contents.empty?
    end

    def validate
      errors.add(self, "filename not specified") if @name.nil?
      errors.add(self, "not found") unless exists?
    end
  end

  class PassphraseFile < TextFile

    def initialize(name='passphrase', options={})
      super name, options
    end

    def validate
      super
      errors.add(self, "is empty") if empty?
    end
  end

  class KeyFile < TextFile

    def initialize(name='encfs6.xml', options={})
      super name, options
    end

    def validate
      super
      errors.add(self, "is empty") if exists? && empty?
    end
  end

  class FileFolder < FileSystemEntity

    def exists?
      !@name.nil? && File.directory?(@name)
    end

    def empty?
      return true unless exists?
      Dir.entries(@name).sort == [".", ".."].sort
    end

    def validate
      errors.add(self, "not found") unless exists?
    end
  end

  class SourceFolder < FileFolder

    def validate
      super
      errors.add(self, "is empty") if exists? && empty?
    end
  end

  class ActionFolder < FileFolder
    attr_accessor :passphrasefile
    attr_accessor :keyfile

    def initialize(name=nil, options={})
      super
      @passphrasefile = PassphraseFile.new(options[:passphrasefile] ? options[:passphrasefile][:name] : nil)
      @keyfile = KeyFile.new(options[:keyfile] ? options[:keyfile][:name] : nil)
      @cmd = options[:cmd]
      @executable = options[:executable]
    end

    def validate
      super
      errors.add(self, "executable filename not specified") unless @executable
      errors.add(self, "#{@executable} executable not found") if executable.empty?
      errors.add(self, "cmd not specified") unless cmd
    end

    def executable
      return nil unless @executable
      result = `which #{@executable}`
      result.strip
    end

    # run the action if valid and return true if successful
    def execute
      raise errors.to_sentences unless valid?

      # default failing command
      result = false

      # protect command from recursion
      mutex = Mutagem::Mutex.new('revenc.lck')
      lock_successful = mutex.execute do
        result = system_cmd(cmd)
      end

      raise "action failed, lock file present" unless lock_successful
      result
    end
  end

  class MountPoint < ActionFolder
    attr_accessor :source

    def initialize(name=nil, source_folder_name=nil, options={})
      super name, options
      @source = SourceFolder.new(source_folder_name)
      @cmd = options[:cmd] || "cat <%= passphrasefile.name %> | ENCFS6_CONFIG=<%= keyfile.name %> \
                              <%= executable %> --stdinpass --reverse <%= source.name %> <%= mountpoint.name %> -- -o ro"
      @executable = options[:executable] || 'encfs'
    end

    # allow clarity in config files, instead of <%= name %> you can use <%= mountpoint.name %>
    def mountpoint
      self
    end

    def validate
      super
      errors.add(self, "is not empty") unless empty?
      errors.add(self, source.errors.to_sentences) unless source.valid?
      errors.add(self, keyfile.errors.to_sentences) unless keyfile.valid?
      errors.add(self, passphrasefile.errors.to_sentences) unless passphrasefile.valid?
    end

  end

  class UnmountPoint < ActionFolder

    def initialize(name=nil, options={})
      super
      @cmd = options[:cmd] || "<%= executable %> -u <%= mountpoint.name %>"
      @executable = options[:executable] || 'fusermount'
    end

    # allow clarity in config files, instead of <%= name %> you can use <%= mountpoint.name %>
    def mountpoint
      self
    end

  end

  class DestinationPoint < BasicAction
  end

  class CopySourceFolder < ActionFolder
    attr_accessor :destination
    attr_accessor :mountpoint

    def initialize(name=nil, destination_name=nil, options={})
      super name, options
      @destination = DestinationPoint.new(destination_name)
      @mountpoint = MountPoint.new(options[:mountpoint])
      @cmd = options[:cmd] || "<%= executable %> -r <%= source.name %> <%= destination.name %>"
      @executable = options[:executable] || 'cp'
    end

    # allow clarity in config files, instead of <%= name %> you can use <%= source.name %>
    def source
      self
    end

    def validate
      super
      errors.add(self, "is empty") if exists? && empty?
      errors.add(self, "mountpoint not found") if (mountpoint.name && !mountpoint.exists?)
      errors.add(self, "mountpoint is empty") if (mountpoint.name && mountpoint.exists? && mountpoint.empty?)
      errors.add(self, destination.errors.to_sentences) unless destination.valid?
    end

  end

end


#require_dependency "../../lib/optimacms/page_services/page_route_service.rb"
#require_dependency "../../lib/optimacms/page_services/page_process_service.rb"

require_dependency "../../lib/optimacms/renderer/admin_page_renderer.rb"

module Optimacms

  class PagesController < Optimacms::ApplicationController
    include ::Optimacms::Mycontroller

    # render
    unless respond_to?(:render_base)
      alias_method :render_base, :render
    end

    include ::Optimacms::Renderer::AdminPageRenderer

    renderer_admin_edit

    def render(options = nil, extra_options = {}, &block)
      options ||= {} # initialise to empty hash if no options specified

      if !current_cms_admin_user
        return render_base(options, extra_options, &block)
      end

      # special cases
      if options.is_a?(Hash) && options[:text]
        return render_base(options, extra_options, &block)
      end

      # editor for admin
      #render_base(options, extra_options, &block)

      render_with_edit(options, extra_options, &block)
    end

=begin
    def my_set_render_template(tpl_view, tpl_layout)
      @optimacms_tpl = tpl_view
      @optimacms_layout = tpl_layout
    end

    def my_set_meta(meta)
      #@optimacms_meta = meta
      @optimacms_meta_title = meta[:title]
      @optimacms_meta_keywords = meta[:keywords]
      @optimacms_meta_description = meta[:description]
    end
=end

    def renderActionInOtherController(controller,action,params, tpl_view=nil, tpl_layout=nil)

      # include render into controller class
      if current_cms_admin_user
        controller.send 'include', Optimacms::Renderer::AdminPageRenderer
        controller.send 'renderer_admin_edit'
      end

      #
      c = controller.new
      c.params = params

      if current_cms_admin_user
        #if !controller.respond_to?(:render_base, true)
        if !c.respond_to?(:render_base, true)
          controller.send :alias_method, :render_base, :render

          controller.send :define_method, "render" do |options = nil, extra_options = {}, &block|
            if current_cms_admin_user && @pagedata
              render_with_edit(options, extra_options, &block)
            else
              render_base(options, extra_options, &block)
            end

          end
        end
      end

      #c.process_action(action, request)
      #c.dispatch(action, request)
      #c.send 'index_page'

      c.request = request
      #c.request.path_parameters = params.with_indifferent_access
      c.request.format = params[:format] || 'html'

      c.action_name = action
      c.response = ActionDispatch::Response.new

      c.send 'my_set_render'
      c.send 'optimacms_set_pagedata', @pagedata
      c.send 'my_set_render_template', tpl_view, tpl_layout
      c.send 'my_set_meta', @pagedata.meta

      #renderer_admin_edit

      #c.process_action(action)
      c.dispatch(action, request, c.response)
      #c.process_action(action, tpl_filename)

      #app = "NewsController".constantize.action(action)
      #app.process params

      # result
      #c

      c.response.body

      #app.response.body
    end

    def show
      @path = params[:url]
      @pagedata = PageServices::PageRouteService.find_page_by_url(@path, current_lang)

      if @pagedata.page.nil?
        not_found and return
      end

      # page mapped to controller
      @pagedata.url_vars.each do |k,v|
        params[k] = v
      end

      # callback
      if respond_to?(:after_init_pagedata)
        send(:after_init_pagedata)
      end

      # process page
      if @pagedata.page.content_page?
        # content page
        #@content = @pagedata.get_content(@page)
        #@content = @page.content

        optimacms_set_pagedata @pagedata
        my_set_render_template @pagedata.template_path, @pagedata.layout.basename
        my_set_meta @pagedata.meta

        # callbacks from main app
        if respond_to?(:before_page_render)
          send(:before_page_render)
        end

        render @optimacms_tpl, :layout=>@optimacms_layout
        #render :text => @content, :layout => @page.layout.name
        return
        respond_to do |format|
          format.html { render :text => @content }
        end
        return
      else
        #@pagedata.generate_content

        #
        #c = renderActionInOtherController(@pagedata.controller_class, @pagedata.action, params, @pagedata.compiled_view_path, @pagedata.layout.basename)
        c = renderActionInOtherController(@pagedata.controller_class, @pagedata.action, params, @pagedata.template_path, @pagedata.layout.basename)

        #puts "#{c}"
        render_base inline: c

        return
=begin
        # THE END

        s = <<-eos
From code

News on page

page = <%=@pg%>

hello

local page = <%=@pg%>

news count = <%=News.all.count%>

render

<%=render 'pages/sub.html.erb'%>

        eos

        #s = File.read(Rails.root+'app/views/pages/news2.html.erb')

        # save template content
        tpl_view = 'pages/1.html.erb'
        fnew = Rails.root+'app/views/'+tpl_view
        File.open(fnew, "w+") do |f|
          f.write(s)
        end

        #
        template = ERB.new(s, 0, "%<>")

        #vv = OpenStruct.new(pg: 75, last: 'Maragall')
        #vv = OpenStruct.new(c.instance_values)
        #ss = template.result(vv.instance_eval { binding })
        #ss = template.result(c.instance_values.instance_eval { binding })
        #ss = template.result(c.get_binding)
        #ss = template.result(c.instance_values.binding())

        #render :text=>ss
        #render :text=>c

        vars = {}
        c.instance_values.each do |k,v|
          vars[k.to_sym] = v
        end

        #render template: 'pages/1.html.erb', locals: vars

        #render template: 'pages/news2.html.erb', locals: {pg: 4}
        #render text: s, locals: {pg: 4}

        #render :text => (render_to_string :template=>'pages/news2.html', :locals=> {pg: 4})
        #render :text => (render_to_string 'pages/news2.html', locals: c.instance_values)
        #render :text => renderActionInOtherController(@pagedata.controller_class, @pagedata.action, params)
=end

      end

    end

    ### page URLs

  end
end


require 'influxdb'

module Rmetrics
  # Handles the comunnication to Influx DB
  class Influx
    def initialize(options = {})
      @influx_client = InfluxDB::Client.new(options)
    end

    def write_data(table, data)
      @influx_client.write_point(table, organize_event(data))
    end

    private

    # rubocop:disable Metrics/MethodLength
    def adjust_values(act, payload)
      payload.each do |key, value|
        case value
        when Hash
          act[:tags].merge!(value.select { |_, v| v.is_a?(String) })
        when Numeric, Integer
          act[:values][key.to_sym] = value.to_f
        when String, TrueClass, FalseClass
          act[:values][key.to_sym] = value
        when Symbol
          act[:values][key.to_sym] = value.to_s
        else
          next
        end
      end
    end
    # rubocop:enable Metrics/MethodLength

    def organize_event(event)
      act = {
        values: {
          duration: event.duration
        },
        tags: {
          name: event.name
        }
      }
      adjust_values(act, event.payload)
      act
    end
  end
end


module HanselCore
  #
  # Class wrapper over httperf.
  #
  class Hansel
    include Formatting
    include Httperf
    include JobQueue

    attr_reader :results, :options

    def initialize options = OpenStruct.new {}
      @options = options
      @results = []
      @current_rate = nil
      @jobs = []
    end

    def config_path
      @config_path ||= File.join [ENV['HOME'], '.hansel']
      FileUtils.mkdir_p @config_path unless File.exists? @config_path
      @config_path
    end

    def output_dir
      @output_dir ||= File.join [ENV['HOME'], 'hansel_output']
      @output_dir
    end

    def register
      response = Typhoeus::Request.get options.master
      @token = JSON.parse(response.body)['token']
    end

    #
    # Output the results based on the requested output format
    #
    def output
      opts = options
      if opts.format
        FileUtils.mkdir_p opts.output_dir
        formatted_output
      end
      @results.clear
    end

    def status text
      puts text if options.verbose
    end

    #
    # Run httperf from low_rate to high_rate, stepping by rate_step
    #
    def run
      while @jobs.length > 0 do
        # do a warm up run first with the highest connection rate
        @current_job = @jobs.pop
        @current_rate = @current_job.high_rate.to_i
        httperf true

        (@current_job.low_rate.to_i..@current_job.high_rate.to_i).
            step(@current_job.rate_step.to_i) do |rate|
          @current_rate = rate
          httperf
        end
        output
      end
    end

    def run_server
      HanselSlaveServer.hansel = self
      HanselSlaveServer.run! :host => 'localhost', :port => 4000
    end

    trap("INT") {
      puts "Terminating."
      Process.exit
    }
  end
end


# -*- ruby -*-

require 'set' # Ruby Standard Library

module LAAG
  class BuildEnvironment
    DEFAULT_FEATURES = Set.new %w[autoconf autoreconf configure make]

    def initialize(library, **options)
      @library  = library
      @options  = options
      @enabled  = Set.new
      @disabled = Set.new
      %i[enable disable].each { |s| [*options[s]].each { |f| send s, f } }
      self
    end

    def script(&block)
      instance_eval(&block) if block_given?
    end

    def execute!(command, *arguments)
      STDOUT.puts ' -- ' + (commandline = [command, *arguments].flatten.map(&:to_s).join(' '))

      Dir.chdir(@library.source_path) do
        system(commandline).tap do |success|
          raise "Error: '#{commandline}' failed" unless success
        end
      end
    end

    def autoreconf!
      return unless enabled?(:autoreconf) and file?('configure.ac')
      execute! 'autoreconf', '--install'
    end

    def autogen!
      return unless enabled?(:autogen) and file?('autogen.sh')
      execute! './autogen.sh'
    end

    def configure!(*arguments)
      return unless enabled?(:configure)
      autogen!    unless file?('configure')
      autoreconf! unless file?('configure')
      return      unless file?('configure')
      execute! './configure', configure_options(arguments)
    end

    def make!(*arguments, make: ENV['MAKE'] || ENV['make'] || 'make')
      return     unless file?(makefile)
      execute! make, "-j#{make_jobs}", arguments
    end

    def configure_options(arguments)
      [
        ("--prefix=#{@library.install_path}" unless disabled?(:prefix)),
        ('--disable-dependency-tracking'     unless enabled?('dependency-tracking')),
        ('--enable-shared'                   unless disabled?(:shared)),
        ('--enable-static'                   unless disabled?(:static)),
        ('--with-pic'                        unless disabled?(:pic)),
        *arguments
      ].flatten.compact.uniq
    end

    def default!(configure: [])
      make!(:clean)          unless disabled?('pre-clean')
      configure!(*configure) unless disabled?(:configure)
      make!                  unless disabled?(:build)
      make! :install         unless disabled?(:install)
      make! :clean           unless disabled?('post-clean')
    end

    #############
    # Detection #
    #############

    def file?(filename)
      return unless filename
      File.exist? File.join(@library.source_path, filename.split('/'))
    end

    def makefile
      RbConfig::CONFIG['MAKEFILES'].split.find { |makefile| file? makefile } || 'Makefile'
    end

    def make_jobs
      @options.fetch(:make_jobs) do
        Etc.respond_to?(:nprocessors) ? Etc.nprocessors : ''
      end
    end

    #################
    # Feature Flags #
    #################

    def features
      DEFAULT_FEATURES
    end

    def disabled
      @disabled - @enabled
    end

    def enabled
      features - disabled
    end

    ######################
    # Flag State Queries #
    ######################

    def enabled?(feature)
      enabled.include? feature.to_s
    end

    def disabled?(feature)
      disabled.include? feature.to_s
    end

    ###########################
    # Flag State Manipulation #
    ###########################

    def enable(feature)
      feature.tap { @enabled << feature.to_s }
    end

    def unenable(feature)
      feature.tap { @enabled.delete feature.to_s }
    end

    def disable(feature)
      feature.tap { @disabled << feature.to_s }
    end

    def undisable(feature)
      feature.tap { @disabled.delete feature.to_s }
    end
  end
end


module Ropenstack
  ##
  # * Name: IdentityVersion2
  # * Description: An implementation of the V2.0 Identity API Client in Ruby
  # * Author: Sam 'Tehsmash' Betts, John Davidge
  # * Date: 30/06/2014
  ##
  module Identity::Version2
          ##
          # Authenticate via keystone, unless a token and tenant are defined then a unscoped
          # token is returned with all associated data and stored in the @data variable.
          # Does not return anything, but all data is accessible through accessor methods.
          ##
          def authenticate(username, password, tenant = nil)
                  data = {
                          "auth" => {
                                  "passwordCredentials" => {
                                          "username" => username,
                                          "password" => password
                                  }
                          }
                  }
                  unless tenant.nil?
                          data["auth"]["tenantName"] = tenant
                  end
                  @data = post_request(address("/tokens"), data, @token)
          end

          ##
          # Scope token provides two ways to call it:
          # 	scope_token(tenantName) => Just using the current token and a tenantName it
          # 				   scopes in the token. Token stays the same.
          #	scope_token(username, password, tenantName) => This uses the username and
          #				   password to reauthenticate with a tenant. The
          #				   token changes.
          ##
          def scope_token(para1, para2 = nil, para3 = nil)
                  if ( para2.nil? )
                          data = { "auth" => { "tenantName" => para1, "token" => { "id" => token() } } }
                          @data = post_request(address("/tokens"), data, token())
                  else
                          authenticate(para1, para2, token(), para3)
                  end
          end

          ##
          # Return the raw @data hash with all the data from authentication.
          ##
          def raw()
                  return @data
          end

          ##
          # Gets the authentication token from the hash and returns it as a string.
          ##
          def token(token = nil)
                  if token.nil?
                          return @data["access"]["token"]["id"]
                  else
                          get_request(address("/tokens/#{token}"), token())
                  end
          end

          ##
          # TODO Add head version of tokens call
          ##
          def token?(token)
                  return false
          end

          ##
          # This returns the token and all metadata associated with the token,
          # including the tenant information.
          ##
          def token_metadata()
                  return @data["access"]["token"]
          end

          ##
          # Return the user hash from the authentication data
          ##
          def user()
                  return @data["access"]["user"]
          end

          ##
          # Returns true if a user is admin.
          ##
          def admin()
                  @data["access"]["user"]["roles"].each do |role|
                          if role["name"].eql?("admin")
                                  return true
                          end
                  end
                  return false
          end

          ##
          # Get the service catalog returned by Identity on authentication.
          ##
          def services()
                  return @data["access"]["serviceCatalog"]
          end

          ##
          # Get the tenant id from the @data
          ##
          def tenant_id()
                  return @data["access"]["token"]["tenant"]["id"]
          end

          def tenant_name()
                  return @data["access"]["token"]["tenant"]["name"]
          end

          # Separate Identity Calls

          def tenant_list()
                  return get_request(address('/tenants'), token())
          end

          ##
          # Add a service to the keystone services directory
          ##
          def add_to_services(name, type, description)
                  data = {
                          'OS-KSADM:service' => {
                                   'name' => name,
                                   'type' => type,
                                   'description' => description
                          }
                  }
                  return post_request(address("/OS-KSADM/services"), data, token())
          end

          ##
          # Get list of services
          ##
          def get_services()
                  return get_request(address("/OS-KSADM/services"), token())
          end

          ##
          # Add an endpoint list
          ##
          def add_endpoint(region, service_id, publicurl, adminurl, internalurl)
                  data = {
                          'endpoint' => {
                                  'region' => region,
                                  'service_id' => service_id,
                                  'publicurl' => publicurl,
                                  'adminurl' => adminurl,
                                  'internalurl' => internalurl
                          }
                  }
                  return post_request(address("/endpoints"), data, token())
          end

          ##
          # Get the endpoint list
          ##
          def get_endpoints(token = nil)
                  if token.nil?
                          return get_request(address("/endpoints"), token())
                  else
                          return get_request(address("/tokens/#{token}/endpoints"), token())
                  end
          end

    def address(endpoint)
      super("/v2.0/" + endpoint)
    end

    def version
      "V2"
    end
  end
end


# MethodDisabling allows a programmer to programatically disable existing methods, causing them to
# raise a NoMethodError, and restore the methods to their original behavior.
#
# The most obvious use case for disabling messages is when you want to ensure that your unit tests
# don't do anything unexpected, such as connecting to external resources.
module MethodDisabling

  # Provides class-level macros for managing disabled methods.
  #
  # @example Disabling an instance method
  #   class Foo
  #     def bar
  #       42
  #     end
  #   end
  #
  #   Foo.new.bar               # => 42
  #   Foo.disable_method :bar
  #   Foo.new.bar               # => NoMethodError: Foo#bar is disabled
  #   Foo.restore_method :bar
  #   Foo.new.bar               # => 42
  #
  # @example Disabling a class method
  #   class Foo
  #     def self.bar
  #       42
  #     end
  #   end
  #
  #   Foo.bar                         # => 42
  #   Foo.disable_class_method :bar
  #   Foo.bar                         # => NoMethodError: #<Class:Foo>#bar is disabled
  #   Foo.restore_class_method :bar
  #   Foo.bar                         # => 42
  #
  module ClassMethods

    # Disables an instance method.
    #
    # @param [Symbol,String]  method_name   The name of the method to disable.
    # @param [String]         message       An error message. Defaults to "Class#method is disabled".
    def disable_method(method_name, message = nil)
      disabled_methods[method_name] ||= DisabledMethod.new(self, method_name, message)
      disabled_methods[method_name].disable!
    end

    # Restores a previously disabled instance method.
    #
    # @param [Symbol,String]  method_name   The name of the method to restore.
    def restore_method(method_name)
      disabled_methods[method_name].restore!
    end

    # A collection of the methods that have been disabled.
    #
    # @return [Hash]
    def disabled_methods
      @disabled_methods ||= {}
    end
    private :disabled_methods

    # Disables a class method.
    #
    # @param [Symbol,String]  method_name   The name of the method to disable.
    # @param [String]         message       An error message. Defaults to "Class#method is disabled".
    def disable_class_method(method_name, message = nil)
      (class << self; self; end).disable_method(method_name, message)
    end

    # Restores a previously disabled class method.
    #
    # @param [Symbol,String]  method_name   The name of the method to restore.
    def restore_class_method(method_name)
      (class << self; self; end).restore_method(method_name)
    end

  end

  # A DisabledMethod is an existing class or instance method that has been disabled. The method can
  # be disabled and restored as necessary. When the method is disabled, calling the method will
  # raise a NoMethodError, optionally with a custom message. When the method is restored, the method
  # will behave as normal.
  #
  # Although this class *could* be used directly, the intention is that you would use the methods in
  # {MethodDisabling::ClassMethods} to disable and restore methods.
  class DisabledMethod

    attr_reader :klass, :method_name, :message

    # Disables a instance method. To disable a class method, pass the class's singleton class as the
    # first argument.
    #
    # @param [Module]         klass         The module or class whose method should be disabled.
    # @param [Symbol,String]  method_name   The name of the method to disable.
    # @param [String]         message       The exception message to be shown when the method is
    #                                       called.
    def initialize(klass, method_name, message = nil)
      @klass       = klass
      @method_name = method_name
      @message     = message || "#{klass.inspect}##{method_name} is disabled"

      alias_method!
      disable!
    end

    # Disables the method.
    def disable!
      @disabled = true
    end

    # Restores the method.
    def restore!
      @disabled = false
    end

    # Returns a Proc that acts as a replacement for the disabled method.
    def to_proc
      disabled_method = self

      # This proc will be evaluated with "self" set to the original object.
      Proc.new do |*args, &block|
        disabled_method.execute(self, *args, &block)
      end
    end

    # The replacement for the original method. It will raise a NoMethodError if the method is
    # disabled. Otherwise, it will execute the original method.
    #
    # @param [Object] object  The "self" object of the method being called.
    # @param [Array]  args    The arguments that were passed to the method.
    # @param [Proc]   block   The block that was passed to the method.
    #
    # @return Whatever the original method returns.
    def execute(object, *args, &block)
      if disabled?
        raise NoMethodError, message
      else
        object.send(aliased_name, *args, &block)
      end
    end

    private

    # Indicates whether or not the method is disabled.
    #
    # @return [Boolean]
    def disabled?
      @disabled
    end

    # Replaces the original implementation of the method with an implementation that allows
    # disabling.
    def alias_method!
      klass.send(:define_method, replacement_name, &self)
      klass.send(:alias_method, aliased_name, method_name)
      klass.send(:alias_method, method_name, replacement_name)
    end

    # The name of the replacement method.
    #
    # @return [String]
    def replacement_name
      "#{base_method_name}_with_disable#{method_suffix}"
    end

    # The aliased name of the original method.
    #
    # @return [String]
    def aliased_name
      "#{base_method_name}_without_disable#{method_suffix}"
    end

    # The original method name with any suffix ("!" or "?") removed.
    #
    # @return [String]
    def base_method_name
      method_name_parts[:base_name]
    end

    # The original method name's suffix ("!" or "?"), if any.
    #
    # @return [String]
    def method_suffix
      method_name_parts[:suffix]
    end

    # The original method name broken into parts. The returned value can is a hash with the keys
    # `:base_name` and `:suffix`, which return the original method name's base name and suffix,
    # respectively.
    #
    # @return [Hash]
    def method_name_parts
      @parts ||= begin
        base_name, suffix = method_name.to_s.sub(/([?!=]?)$/, ""), $1
        { :base_name => base_name, :suffix => suffix }
      end
    end

  end

end

# Yeah, it's including ClassMethods, which isn't usual, but that's because it's being included on
# the Module class, which effectively makes them class methods in other classes and modules.
Module.send(:include, MethodDisabling::ClassMethods)


module Semistatic
  class Page < ActiveRecord::Base
    attr_accessible :slug, :title, :template_name, :parts_attributes

    has_many :parts
    accepts_nested_attributes_for :parts

    validates :slug, presence: true, uniqueness: { case_sensitive: false }
    validates :title, presence: true

    # get part by its name
    # param
    # @return Part
    def part(name)
      parts.select {|p| p.name.downcase == name.to_s.downcase }.first
    end

    # Factory a page from the config
    #     Creates the attributes required by the config
    # @param String template_name
    # @param Hash options # the page configuration
    # @return Page
    def self.factory(template_name, options)
      page = new(template_name: template_name)

      options = HashWithIndifferentAccess.new(options)
      options[:parts].each do |name, attributes|
        part = page.parts.build({ name: name })
        part.options = attributes
      end

      page.save(validate: false)
      page
    end
  end
end