/*  Copyright (C) 2008--2010 Joshua Judson Rosen <rozzin@geekspace.com>.

    This program is free software: you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    version 3 as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; see the file COPYING. If not, see
    <http://www.gnu.org/licenses/> or write to:

        The Free Software Foundation, inc.
        51 Franklin Street, Fifth Floor
        Boston, MA 02110-1301
        USA
*/

#include <stdlib.h>

#include <glib/grand.h>
#include "virand/random.h"

#include <math.h>
#include <cairo.h>

#include <glib-object.h>
#include "graphics.h"
#include "metashape.h"
#include "shape.h"


struct _VisualID_ShapeClass {
  VisualID_MetashapeClass parent_class;
};

G_DEFINE_TYPE (VisualID_Shape, visualid_shape, VISUALID_TYPE_METASHAPE)

static void
shape_constructed (GObject *self)
{
  VisualID_Metashape *shape = VISUALID_METASHAPE (self);
  VisualID_Glyph *glyph = VISUALID_GLYPH (self);

  G_OBJECT_CLASS (visualid_shape_parent_class)->constructed (self);

  if (!virand_prob_reduced (glyph->generator->state,
                            .6, glyph->recursion_level)) {
    shape->inside_child = NULL;
  } else {
    visualid_glyph_spawn (glyph, "inside-child");
    shape->ic_scale = g_rand_double_range (glyph->generator->state, .1, 2)
      / shape->n;
  }
}

enum {
  PROP_INSIDE_CHILD = 1,
  PROP_INSIDE_CHILD_SCALE
};

static void
shape_get_property (GObject *object,
                    guint property_id,
                    GValue *value,
                    GParamSpec *pspec)
{
  VisualID_Metashape *self = VISUALID_METASHAPE (object);

  switch (property_id)
    {
    case PROP_INSIDE_CHILD:
      g_value_set_object (value, self->inside_child);
      break;
    case PROP_INSIDE_CHILD_SCALE:
      g_value_set_double (value, self->ic_scale);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static void
shape_set_property (GObject *object,
                    guint property_id,
                    const GValue *value,
                    GParamSpec *pspec)
{
  VisualID_Metashape *self = VISUALID_METASHAPE (object);

  switch (property_id)
    {
    case PROP_INSIDE_CHILD:
      visualid_glyph_take_child (VISUALID_GLYPH (self),
                                 g_value_get_object (value),
                                 &self->inside_child);
      break;
    case PROP_INSIDE_CHILD_SCALE:
      self->ic_scale = g_value_get_double (value);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

static int
visualid_shape_complexity (VisualID_Metashape *shape, int recurse)
{
  int complexity = visualid_metashape_complexity (shape, recurse);

  if (recurse--) {
    if (shape->inside_child) {
      complexity += (visualid_glyph_complexity (shape->inside_child, recurse)
                     * shape->n);
    }
  }

  return complexity;
}

static void
visualid_shape_init (VisualID_Shape *self)
{
}

static void
visualid_shape_class_init (VisualID_ShapeClass *class)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);

  VISUALID_GLYPH_CLASS (class)->produce =
    (producer_fn *) visualid_metashape_exec;
  VISUALID_GLYPH_CLASS (class)->complexity_fn =
    (complexity_fn *) visualid_shape_complexity;

  gobject_class->get_property = shape_get_property;
  gobject_class->set_property = shape_set_property;
  gobject_class->constructed = shape_constructed;

  g_object_class_install_property
    (gobject_class, PROP_INSIDE_CHILD,
     g_param_spec_object ("inside-child",
                          "Inside child",
                          "Glyph to replicate inside the shape",
                          VISUALID_TYPE_GLYPH,
                          G_PARAM_READWRITE));
  g_object_class_install_property
    (gobject_class, PROP_INSIDE_CHILD_SCALE,
     g_param_spec_double ("inside-child-scale",
                          "Inside-child scale",
                          "Relative scale of the glyphs replicated inside the shape",
                          .1/(2<<6), 2.0/(2<<3), (.1+2.0)/2.0/(2<<4),
                          G_PARAM_READWRITE));
}
