/**
 * @file llparcel.h
 *
 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#ifndef LL_LLPARCEL_H
#define LL_LLPARCEL_H

#include <time.h>
#include <iostream>

#include "lluuid.h"
#include "llparcelflags.h"
#include "llpermissions.h"
#include "lltimer.h"
#include "v3math.h"
#include "llsettingsdaycycle.h"

// Grid out of which parcels taken is stepped every 4 meters.
const F32 PARCEL_GRID_STEP_METERS   = 4.f;

// Area of one "square" of parcel
const S32 PARCEL_UNIT_AREA          = 16;

// Height _above_ground_ that parcel boundary ends
const F32 PARCEL_HEIGHT = 50.f;

//Height above ground which parcel boundries exist for explicitly banned avatars
const F32 BAN_HEIGHT = 5000.f;

// Maximum number of entries in an access list
const S32 PARCEL_MAX_ACCESS_LIST = 300;
//Maximum number of entires in an update packet
//for access/ban lists.
const F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f;

// Maximum number of experiences
const S32 PARCEL_MAX_EXPERIENCE_LIST = 24;

// Weekly charge for listing a parcel in the directory
const S32 PARCEL_DIRECTORY_FEE = 30;

const S32 PARCEL_PASS_PRICE_DEFAULT = 10;
const F32 PARCEL_PASS_HOURS_DEFAULT = 1.f;

// Number of "chunks" in which parcel overlay data is sent
// Chunk 0 = southern rows, entire width
const S32 PARCEL_OVERLAY_CHUNKS = 4;

// Bottom three bits are a color index for the land overlay
const U8 PARCEL_COLOR_MASK  = 0x07;
const U8 PARCEL_PUBLIC      = 0x00;
const U8 PARCEL_OWNED       = 0x01;
const U8 PARCEL_GROUP       = 0x02;
const U8 PARCEL_SELF        = 0x03;
const U8 PARCEL_FOR_SALE    = 0x04;
const U8 PARCEL_AUCTION     = 0x05;
// unused 0x06
// unused 0x07
// flag, unused 0x08
const U8 PARCEL_HIDDENAVS   = 0x10; // avatars not visible outside of parcel.  Used for 'see avs' feature, but must be off for compatibility
const U8 PARCEL_SOUND_LOCAL = 0x20;
const U8 PARCEL_WEST_LINE   = 0x40; // flag, property line on west edge
const U8 PARCEL_SOUTH_LINE  = 0x80; // flag, property line on south edge

// Transmission results for parcel properties
const S32 PARCEL_RESULT_NO_DATA = -1;
const S32 PARCEL_RESULT_SUCCESS = 0;    // got exactly one parcel
const S32 PARCEL_RESULT_MULTIPLE = 1;   // got multiple parcels

const S32 SELECTED_PARCEL_SEQ_ID = -10000;
const S32 COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID =  -20000;
const S32 COLLISION_BANNED_PARCEL_SEQ_ID = -30000;
const S32 COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID =  -40000;
const S32 HOVERED_PARCEL_SEQ_ID =  -50000;

const U32 RT_NONE   = 0x1 << 0;
const U32 RT_OWNER  = 0x1 << 1;
const U32 RT_GROUP  = 0x1 << 2;
const U32 RT_OTHER  = 0x1 << 3;
const U32 RT_LIST   = 0x1 << 4;
const U32 RT_SELL   = 0x1 << 5;

const S32 INVALID_PARCEL_ID = -1;

const S32 INVALID_PARCEL_ENVIRONMENT_VERSION = -2;
// if Region settings are used, parcel env. version is -1
const S32 UNSET_PARCEL_ENVIRONMENT_VERSION = -1;

// Timeouts for parcels
// default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000
const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
// ***** TESTING is 10 minutes
//const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(600000000);

// group is 60 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 5184000000000
const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
// ***** TESTING is 10 minutes
//const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(600000000);

// default sale timeout is 2 days -> 172800000000
const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
// ***** TESTING is 10 minutes
//const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(600000000);

// more grace period extensions.
const U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);

// if more than 100,000s before sale revert, and no extra extension
// has been given, go ahead and extend it more. That's about 1.2 days.
const S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;



class LLMessageSystem;
class LLSD;

class LLAccessEntry
{
public:

    typedef std::map<LLUUID,LLAccessEntry> map;

    LLAccessEntry()
    :   mTime(0),
        mFlags(0)
    {}

    LLUUID      mID;        // Agent ID
    S32         mTime;      // Time (unix seconds) when entry expires
    U32         mFlags;     // Not used - currently should always be zero
};


class LLParcel
{
public:
    enum EOwnershipStatus
    {
        OS_LEASED = 0,
        OS_LEASE_PENDING = 1,
        OS_ABANDONED = 2,
        OS_COUNT = 3,
        OS_NONE = -1
    };
    enum ECategory
    {
        C_NONE = 0,
        C_LINDEN,
        C_ADULT,
        C_ARTS,         // "arts & culture"
        C_BUSINESS,     // was "store"
        C_EDUCATIONAL,
        C_GAMING,       // was "game"
        C_HANGOUT,      // was "gathering place"
        C_NEWCOMER,
        C_PARK,         // "parks & nature"
        C_RESIDENTIAL,  // was "homestead"
        C_SHOPPING,
        C_STAGE,
        C_OTHER,
        C_RENTAL,
        C_COUNT,
        C_ANY = -1      // only useful in queries
    };
    enum EAction
    {
        A_CREATE = 0,
        A_RELEASE = 1,
        A_ABSORB = 2,
        A_ABSORBED = 3,
        A_DIVIDE = 4,
        A_DIVISION = 5,
        A_ACQUIRE = 6,
        A_RELINQUISH = 7,
        A_CONFIRM = 8,
        A_COUNT = 9,
        A_UNKNOWN = -1
    };

    enum ELandingType
    {
        L_NONE = 0,
        L_LANDING_POINT = 1,
        L_DIRECT = 2
    };

    // CREATORS
    LLParcel();
    LLParcel(
        const LLUUID &owner_id,
        BOOL modify,
        BOOL terraform,
        BOOL damage,
        time_t claim_date,
        S32 claim_price,
        S32 rent_price,
        S32 area,
        S32 sim_object_limit,
        F32 parcel_object_bonus,
        BOOL is_group_owned = FALSE);
    virtual ~LLParcel();

    void init(
        const LLUUID &owner_id,
        BOOL modify,
        BOOL terraform,
        BOOL damage,
        time_t claim_date,
        S32 claim_price,
        S32 rent_price,
        S32 area,
        S32 sim_object_limit,
        F32 parcel_object_bonus,
        BOOL is_group_owned = FALSE);

    // TODO: make an actual copy constructor for this
    void overrideParcelFlags(U32 flags);
    // if you specify an agent id here, the group id will be zeroed
    void overrideOwner(
        const LLUUID& owner_id,
        BOOL is_group_owned = FALSE);
    void overrideSaleTimerExpires(F32 secs_left) { mSaleTimerExpires.setTimerExpirySec(secs_left); }

    // MANIPULATORS
    void generateNewID() { mID.generate(); }
    void setName(const std::string& name);
    void setDesc(const std::string& desc);
    void setMusicURL(const std::string& url);
    void setMediaURL(const std::string& url);
    void setMediaType(const std::string& type);
    void setMediaDesc(const std::string& desc);
    void    setMediaID(const LLUUID& id) { mMediaID = id; }
    void    setMediaAutoScale ( U8 flagIn ) { mMediaAutoScale = flagIn; }
    void    setMediaLoop (U8 loop) { mMediaLoop = loop; }
    void setMediaWidth(S32 width);
    void setMediaHeight(S32 height);
    void setMediaCurrentURL(const std::string& url);
    void setMediaAllowNavigate(U8 enable) { mMediaAllowNavigate = enable; }
    void setMediaURLTimeout(F32 timeout) { mMediaURLTimeout = timeout; }
    void setMediaPreventCameraZoom(U8 enable) { mMediaPreventCameraZoom = enable; }

    void setMediaURLResetTimer(F32 time);
    virtual void    setLocalID(S32 local_id);

    // blow away all the extra stuff lurking in parcels, including urls, access lists, etc
    void clearParcel();

    // This value is not persisted out to the parcel file, it is only
    // a per-process blocker for attempts to purchase.
    void setInEscrow(bool in_escrow) { mInEscrow = in_escrow; }

    void setAuthorizedBuyerID(const LLUUID& id) { mAuthBuyerID = id; }
    //void overrideBuyerID(const LLUUID& id) { mBuyerID = id; }
    void setCategory(ECategory category) { mCategory = category; }
    void setSnapshotID(const LLUUID& id) { mSnapshotID = id; }
    void setUserLocation(const LLVector3& pos)  { mUserLocation = pos; }
    void setUserLookAt(const LLVector3& rot)    { mUserLookAt = rot; }
    void setLandingType(const ELandingType type) { mLandingType = type; }
    void setSeeAVs(BOOL see_avs)    { mSeeAVs = see_avs;    }
    void setHaveNewParcelLimitData(bool have_new_parcel_data)       { mHaveNewParcelLimitData = have_new_parcel_data;       }       // Remove this once hidden AV feature is fully available grid-wide

    void setAuctionID(U32 auction_id) { mAuctionID = auction_id;}

    void    setAllParcelFlags(U32 flags);
    void    setParcelFlag(U32 flag, BOOL b);

    virtual void setArea(S32 area, S32 sim_object_limit);
    void    setDiscountRate(F32 rate);

    void    setAllowModify(BOOL b)  { setParcelFlag(PF_CREATE_OBJECTS, b); }
    void    setAllowGroupModify(BOOL b) { setParcelFlag(PF_CREATE_GROUP_OBJECTS, b); }
    void    setAllowAllObjectEntry(BOOL b)  { setParcelFlag(PF_ALLOW_ALL_OBJECT_ENTRY, b); }
    void    setAllowGroupObjectEntry(BOOL b)    { setParcelFlag(PF_ALLOW_GROUP_OBJECT_ENTRY, b); }
    void    setAllowTerraform(BOOL b){setParcelFlag(PF_ALLOW_TERRAFORM, b); }
    void    setAllowDamage(BOOL b)  { setParcelFlag(PF_ALLOW_DAMAGE, b); }
    void    setAllowFly(BOOL b)     { setParcelFlag(PF_ALLOW_FLY, b); }
    void    setAllowGroupScripts(BOOL b)    { setParcelFlag(PF_ALLOW_GROUP_SCRIPTS, b); }
    void    setAllowOtherScripts(BOOL b)    { setParcelFlag(PF_ALLOW_OTHER_SCRIPTS, b); }
    void    setAllowDeedToGroup(BOOL b) { setParcelFlag(PF_ALLOW_DEED_TO_GROUP, b); }
    void    setContributeWithDeed(BOOL b) { setParcelFlag(PF_CONTRIBUTE_WITH_DEED, b); }
    void    setForSale(BOOL b)      { setParcelFlag(PF_FOR_SALE, b); }
    void    setSoundOnly(BOOL b)    { setParcelFlag(PF_SOUND_LOCAL, b); }
    void    setDenyAnonymous(BOOL b) { setParcelFlag(PF_DENY_ANONYMOUS, b); }
    void    setDenyAgeUnverified(BOOL b) { setParcelFlag(PF_DENY_AGEUNVERIFIED, b); }
    void    setRestrictPushObject(BOOL b) { setParcelFlag(PF_RESTRICT_PUSHOBJECT, b); }
    void    setAllowGroupAVSounds(BOOL b)   { mAllowGroupAVSounds = b;      }
    void    setAllowAnyAVSounds(BOOL b)     { mAllowAnyAVSounds = b;        }
    void    setObscureMOAP(bool b)  { mObscureMOAP = b; }

    void    setDrawDistance(F32 dist)   { mDrawDistance = dist; }
    void    setSalePrice(S32 price)     { mSalePrice = price; }
    void    setGroupID(const LLUUID& id)    { mGroupID = id; }
    //void  setGroupName(const std::string& s)  { mGroupName.assign(s); }
    void    setPassPrice(S32 price)             { mPassPrice = price; }
    void    setPassHours(F32 hours)             { mPassHours = hours; }

//  BOOL    importStream(std::istream& input_stream);
    BOOL    importAccessEntry(std::istream& input_stream, LLAccessEntry* entry);
    // BOOL exportStream(std::ostream& output_stream);

    void    packMessage(LLMessageSystem* msg);
    void    packMessage(LLSD& msg);
    void    unpackMessage(LLMessageSystem* msg);

    void    packAccessEntries(LLMessageSystem* msg,
                                const std::map<LLUUID,LLAccessEntry>& list);
    void    unpackAccessEntries(LLMessageSystem* msg,
                                std::map<LLUUID,LLAccessEntry>* list);

    void    unpackExperienceEntries(LLMessageSystem* msg, U32 type);


    void    setAABBMin(const LLVector3& min)    { mAABBMin = min; }
    void    setAABBMax(const LLVector3& max)    { mAABBMax = max; }

    // Extend AABB to include rectangle from min to max.
    void extendAABB(const LLVector3& box_min, const LLVector3& box_max);

    void dump();

    // Scans the pass list and removes any items with an expiration
    // time earlier than "now".
    void expirePasses(S32 now);

    // Add to list, suppressing duplicates.  Returns TRUE if added.
    BOOL addToAccessList(const LLUUID& agent_id, S32 time);
    BOOL addToBanList(const LLUUID& agent_id, S32 time);
    BOOL removeFromAccessList(const LLUUID& agent_id);
    BOOL removeFromBanList(const LLUUID& agent_id);

    // ACCESSORS
    const LLUUID&   getID() const               { return mID; }
    const std::string&  getName() const         { return mName; }
    const std::string&  getDesc() const         { return mDesc; }
    const std::string&  getMusicURL() const     { return mMusicURL; }
    const std::string&  getMediaURL() const     { return mMediaURL; }
    const std::string&  getMediaDesc() const    { return mMediaDesc; }
    const std::string&  getMediaType() const    { return mMediaType; }
    const LLUUID&   getMediaID() const          { return mMediaID; }
    S32             getMediaWidth() const       { return mMediaWidth; }
    S32             getMediaHeight() const      { return mMediaHeight; }
    U8              getMediaAutoScale() const   { return mMediaAutoScale; }
    U8              getMediaLoop() const        { return mMediaLoop; }
    const std::string&  getMediaCurrentURL() const { return mMediaCurrentURL; }
    U8              getMediaAllowNavigate() const { return mMediaAllowNavigate; }
    F32             getMediaURLTimeout() const { return mMediaURLTimeout; }
    U8              getMediaPreventCameraZoom() const { return mMediaPreventCameraZoom; }

    S32             getLocalID() const          { return mLocalID; }
    const LLUUID&   getOwnerID() const          { return mOwnerID; }
    const LLUUID&   getGroupID() const          { return mGroupID; }
    S32             getPassPrice() const        { return mPassPrice; }
    F32             getPassHours() const        { return mPassHours; }
    BOOL            getIsGroupOwned() const     { return mGroupOwned; }

    U32 getAuctionID() const    { return mAuctionID; }
    bool isInEscrow() const     { return mInEscrow; }

    BOOL isPublic() const;

    // Region-local user-specified position
    const LLVector3& getUserLocation() const    { return mUserLocation; }
    const LLVector3& getUserLookAt() const  { return mUserLookAt; }
    ELandingType getLandingType() const { return mLandingType; }
    BOOL getSeeAVs() const          { return mSeeAVs;       }
    BOOL getHaveNewParcelLimitData() const      { return mHaveNewParcelLimitData;   }

    // User-specified snapshot
    const LLUUID&   getSnapshotID() const       { return mSnapshotID; }

    // the authorized buyer id is the person who is the only
    // agent/group that has authority to purchase. (ie, ui specified a
    // particular agent could buy the plot).
    const LLUUID& getAuthorizedBuyerID() const { return mAuthBuyerID; }

    // helper function
    BOOL isBuyerAuthorized(const LLUUID& buyer_id) const;

    // The buyer of a plot is set when someone indicates they want to
    // buy the plot, and the system is simply waiting for tier-up
    // approval
    //const LLUUID& getBuyerID() const { return mBuyerID; }

    // functions to deal with ownership status.
    EOwnershipStatus getOwnershipStatus() const { return mStatus; }
    static const std::string& getOwnershipStatusString(EOwnershipStatus status);
    void setOwnershipStatus(EOwnershipStatus status) { mStatus = status; }

    // dealing with parcel category information
    ECategory getCategory() const {return mCategory; }
    static const std::string& getCategoryString(ECategory category);
    static const std::string& getCategoryUIString(ECategory category);
    static ECategory getCategoryFromString(const std::string& string);
    static ECategory getCategoryFromUIString(const std::string& string);

    // functions for parcel action (used for logging)
    static const std::string& getActionString(EAction action);

    // dealing with sales and parcel conversion.
    //
    // the isSaleTimerExpired will trivially return FALSE if there is
    // no sale going on. Pass in the current time in usec which will
    // be used for comparison.
    BOOL isSaleTimerExpired(const U64& time);

    F32 getSaleTimerExpires() { return mSaleTimerExpires.getRemainingTimeF32(); }

    // should the parcel join on complete?
    //U32 getJoinNeighbors() const { return mJoinNeighbors; }

    // need to record a few things with the parcel when a sale
    // starts.
    void startSale(const LLUUID& buyer_id, BOOL is_buyer_group);

    // do the expiration logic, which needs to return values usable in
    // a L$ transaction.
    void expireSale(U32& type, U8& flags, LLUUID& from_id, LLUUID& to_id);
    void completeSale(U32& type, U8& flags, LLUUID& to_id);
    void clearSale();


    BOOL isMediaResetTimerExpired(const U64& time);


    // more accessors
    U32     getParcelFlags() const          { return mParcelFlags; }

    BOOL    getParcelFlag(U32 flag) const
                    { return (mParcelFlags & flag) ? TRUE : FALSE; }

    // objects can be added or modified by anyone (only parcel owner if disabled)
    BOOL    getAllowModify() const
                    { return (mParcelFlags & PF_CREATE_OBJECTS) ? TRUE : FALSE; }

    // objects can be added or modified by group members
    BOOL    getAllowGroupModify() const
                    { return (mParcelFlags & PF_CREATE_GROUP_OBJECTS) ? TRUE : FALSE; }

    // the parcel can be deeded to the group
    BOOL    getAllowDeedToGroup() const
                    { return (mParcelFlags & PF_ALLOW_DEED_TO_GROUP) ? TRUE : FALSE; }

    // Does the owner want to make a contribution along with the deed.
    BOOL getContributeWithDeed() const
    { return (mParcelFlags & PF_CONTRIBUTE_WITH_DEED) ? TRUE : FALSE; }

    // heightfield can be modified
    BOOL    getAllowTerraform() const
                    { return (mParcelFlags & PF_ALLOW_TERRAFORM) ? TRUE : FALSE; }

    // avatars can be hurt here
    BOOL    getAllowDamage() const
                    { return (mParcelFlags & PF_ALLOW_DAMAGE) ? TRUE : FALSE; }

    BOOL    getAllowFly() const
                    { return (mParcelFlags & PF_ALLOW_FLY) ? TRUE : FALSE; }

    BOOL    getAllowGroupScripts() const
                    { return (mParcelFlags & PF_ALLOW_GROUP_SCRIPTS) ? TRUE : FALSE; }

    BOOL    getAllowOtherScripts() const
                    { return (mParcelFlags & PF_ALLOW_OTHER_SCRIPTS) ? TRUE : FALSE; }

    BOOL    getAllowAllObjectEntry() const
                    { return (mParcelFlags & PF_ALLOW_ALL_OBJECT_ENTRY) ? TRUE : FALSE; }

    BOOL    getAllowGroupObjectEntry() const
                    { return (mParcelFlags & PF_ALLOW_GROUP_OBJECT_ENTRY) ? TRUE : FALSE; }

    BOOL    getForSale() const
                    { return (mParcelFlags & PF_FOR_SALE) ? TRUE : FALSE; }
    BOOL    getSoundLocal() const
                    { return (mParcelFlags & PF_SOUND_LOCAL) ? TRUE : FALSE; }
    BOOL    getParcelFlagAllowVoice() const
                    { return (mParcelFlags & PF_ALLOW_VOICE_CHAT) ? TRUE : FALSE; }
    BOOL    getParcelFlagUseEstateVoiceChannel() const
                    { return (mParcelFlags & PF_USE_ESTATE_VOICE_CHAN) ? TRUE : FALSE; }
    BOOL    getAllowPublish() const
                    { return (mParcelFlags & PF_ALLOW_PUBLISH) ? TRUE : FALSE; }
    BOOL    getMaturePublish() const
                    { return (mParcelFlags & PF_MATURE_PUBLISH) ? TRUE : FALSE; }
    BOOL    getRestrictPushObject() const
                    { return (mParcelFlags & PF_RESTRICT_PUSHOBJECT) ? TRUE : FALSE; }
    BOOL    getRegionPushOverride() const
                    { return mRegionPushOverride; }
    BOOL    getRegionDenyAnonymousOverride() const
                    { return mRegionDenyAnonymousOverride; }
    BOOL    getRegionDenyAgeUnverifiedOverride() const
                    { return mRegionDenyAgeUnverifiedOverride; }
    BOOL    getRegionAllowAccessOverride() const
                    { return mRegionAllowAccessoverride; }
    BOOL    getRegionAllowEnvironmentOverride() const
                    { return mRegionAllowEnvironmentOverride; }
    S32     getParcelEnvironmentVersion() const
                    { return mCurrentEnvironmentVersion; }


    BOOL    getAllowGroupAVSounds() const   { return mAllowGroupAVSounds;   }
    BOOL    getAllowAnyAVSounds()   const   { return mAllowAnyAVSounds;     }

    bool    getObscureMOAP() const { return mObscureMOAP; }

    F32     getDrawDistance() const         { return mDrawDistance; }
    S32     getSalePrice() const            { return mSalePrice; }
    time_t  getClaimDate() const            { return mClaimDate; }
    S32     getClaimPricePerMeter() const   { return mClaimPricePerMeter; }
    S32     getRentPricePerMeter() const    { return mRentPricePerMeter; }

    // Area is NOT automatically calculated.  You must calculate it
    // and store it with setArea.
    S32     getArea() const                 { return mArea; }

    // deprecated 12/11/2003
    //F32       getDiscountRate() const         { return mDiscountRate; }

    S32     getClaimPrice() const           { return mClaimPricePerMeter * mArea; }

    // Can this agent create objects here?
    BOOL    allowModifyBy(const LLUUID &agent_id, const LLUUID &group_id) const;

    // Can this agent change the shape of the land?
    BOOL    allowTerraformBy(const LLUUID &agent_id) const;

    bool    operator==(const LLParcel &rhs) const;

    // Calculate rent - area * rent * discount rate
    S32     getTotalRent() const;
    F32     getAdjustedRentPerMeter() const;

    const LLVector3&    getAABBMin() const      { return mAABBMin; }
    const LLVector3&    getAABBMax() const      { return mAABBMax; }
    LLVector3 getCenterpoint() const;

    // simwide
    S32     getSimWideMaxPrimCapacity() const { return mSimWideMaxPrimCapacity; }
    S32 getSimWidePrimCount() const { return mSimWidePrimCount; }

    // this parcel only (not simwide)
    S32     getMaxPrimCapacity() const  { return mMaxPrimCapacity; }    // Does not include prim bonus
    S32     getPrimCount() const        { return mOwnerPrimCount + mGroupPrimCount + mOtherPrimCount + mSelectedPrimCount; }
    S32     getOwnerPrimCount() const   { return mOwnerPrimCount; }
    S32     getGroupPrimCount() const   { return mGroupPrimCount; }
    S32     getOtherPrimCount() const   { return mOtherPrimCount; }
    S32     getSelectedPrimCount() const{ return mSelectedPrimCount; }
    S32     getTempPrimCount() const    { return mTempPrimCount; }
    F32     getParcelPrimBonus() const  { return mParcelPrimBonus; }

    S32     getCleanOtherTime() const           { return mCleanOtherTime; }

    void    setMaxPrimCapacity(S32 max) { mMaxPrimCapacity = max; }     // Does not include prim bonus
    // simwide
    void    setSimWideMaxPrimCapacity(S32 current)  { mSimWideMaxPrimCapacity = current; }
    void setSimWidePrimCount(S32 current) { mSimWidePrimCount = current; }

    // this parcel only (not simwide)
    void    setOwnerPrimCount(S32 current)  { mOwnerPrimCount = current; }
    void    setGroupPrimCount(S32 current)  { mGroupPrimCount = current; }
    void    setOtherPrimCount(S32 current)  { mOtherPrimCount = current; }
    void    setSelectedPrimCount(S32 current)   { mSelectedPrimCount = current; }
    void    setTempPrimCount(S32 current)   { mTempPrimCount = current; }
    void    setParcelPrimBonus(F32 bonus)   { mParcelPrimBonus = bonus; }

    void    setCleanOtherTime(S32 time)                 { mCleanOtherTime = time; }
    void    setRegionPushOverride(BOOL override) {mRegionPushOverride = override; }
    void    setRegionDenyAnonymousOverride(BOOL override)   { mRegionDenyAnonymousOverride = override; }
    void    setRegionDenyAgeUnverifiedOverride(BOOL override)   { mRegionDenyAgeUnverifiedOverride = override; }
    void    setRegionAllowAccessOverride(BOOL override) { mRegionAllowAccessoverride = override; }
    void    setRegionAllowEnvironmentOverride(BOOL override) { mRegionAllowEnvironmentOverride = override; }

    void    setParcelEnvironmentVersion(S32 version) { mCurrentEnvironmentVersion = version; }

    // Accessors for parcel sellWithObjects
    void    setPreviousOwnerID(LLUUID prev_owner)   { mPreviousOwnerID = prev_owner; }
    void    setPreviouslyGroupOwned(BOOL b)         { mPreviouslyGroupOwned = b; }
    void    setSellWithObjects(BOOL b)              { setParcelFlag(PF_SELL_PARCEL_OBJECTS, b); }

    LLUUID  getPreviousOwnerID() const      { return mPreviousOwnerID; }
    BOOL    getPreviouslyGroupOwned() const { return mPreviouslyGroupOwned; }
    BOOL    getSellWithObjects() const      { return (mParcelFlags & PF_SELL_PARCEL_OBJECTS) ? TRUE : FALSE; }

protected:
    LLUUID mID;
    LLUUID              mOwnerID;
    LLUUID              mGroupID;
    BOOL                mGroupOwned; // TRUE if mOwnerID is a group_id
    LLUUID              mPreviousOwnerID;
    BOOL                mPreviouslyGroupOwned;

    EOwnershipStatus mStatus;
    ECategory mCategory;
    LLUUID mAuthBuyerID;
    LLUUID mSnapshotID;
    LLVector3 mUserLocation;
    LLVector3 mUserLookAt;
    ELandingType mLandingType;
    BOOL mSeeAVs;                           // Avatars on this parcel are visible from outside it
    BOOL mHaveNewParcelLimitData;           // Remove once hidden AV feature is grid-wide
    LLTimer mSaleTimerExpires;
    LLTimer mMediaResetTimer;

    S32 mGraceExtension;

    // This value is non-zero if there is an auction associated with
    // the parcel.
    U32 mAuctionID;

    // value used to temporarily lock attempts to purchase the parcel.
    bool mInEscrow;

    time_t              mClaimDate;             // UTC Unix-format time
    S32                 mClaimPricePerMeter;    // meter squared
    S32                 mRentPricePerMeter;     // meter squared
    S32                 mArea;                  // meter squared
    F32                 mDiscountRate;          // 0.0-1.0
    F32                 mDrawDistance;
    U32                 mParcelFlags;
    S32                 mSalePrice;             // linden dollars
    std::string         mName;
    std::string         mDesc;
    std::string         mMusicURL;
    std::string         mMediaURL;
    std::string         mMediaDesc;
    std::string         mMediaType;
    S32                 mMediaWidth;
    S32                 mMediaHeight;
    U8                  mMediaAutoScale;
    U8                  mMediaLoop;
    std::string         mMediaCurrentURL;
    LLUUID              mMediaID;
    U8                  mMediaAllowNavigate;
    U8                  mMediaPreventCameraZoom;
    F32                 mMediaURLTimeout;
    S32                 mPassPrice;
    F32                 mPassHours;
    LLVector3           mAABBMin;
    LLVector3           mAABBMax;
    S32                 mMaxPrimCapacity;       // Prims allowed on parcel, does not include prim bonus
    S32                 mSimWidePrimCount;
    S32                 mSimWideMaxPrimCapacity;
    //S32                   mSimWidePrimCorrection;
    S32                 mOwnerPrimCount;
    S32                 mGroupPrimCount;
    S32                 mOtherPrimCount;
    S32                 mSelectedPrimCount;
    S32                 mTempPrimCount;
    F32                 mParcelPrimBonus;
    S32                 mCleanOtherTime;
    BOOL                mRegionPushOverride;
    BOOL                mRegionDenyAnonymousOverride;
    BOOL                mRegionDenyAgeUnverifiedOverride;
    BOOL                mRegionAllowAccessoverride;
    BOOL                mRegionAllowEnvironmentOverride;
    BOOL                mAllowGroupAVSounds;
    BOOL                mAllowAnyAVSounds;
    bool                mObscureMOAP;
    S32                 mCurrentEnvironmentVersion;

    bool                mIsDefaultDayCycle;

public:
    // HACK, make private
    S32                 mLocalID;
    LLUUID              mBanListTransactionID;
    LLUUID              mAccessListTransactionID;
    std::map<LLUUID,LLAccessEntry>  mAccessList;
    std::map<LLUUID,LLAccessEntry>  mBanList;
    std::map<LLUUID,LLAccessEntry>  mTempBanList;
    std::map<LLUUID,LLAccessEntry>  mTempAccessList;

    typedef std::map<LLUUID, U32> xp_type_map_t;

    void setExperienceKeyType(const LLUUID& experience_key, U32 type);
    U32 countExperienceKeyType(U32 type);
    U32 getExperienceKeyType(const LLUUID& experience_key)const;
    LLAccessEntry::map getExperienceKeysByType(U32 type)const;
    void clearExperienceKeysByType(U32 type);

private:
    xp_type_map_t mExperienceKeys;

};


const std::string& ownership_status_to_string(LLParcel::EOwnershipStatus status);
LLParcel::EOwnershipStatus ownership_string_to_status(const std::string& s);
LLParcel::ECategory category_string_to_category(const std::string& s);
const std::string& category_to_string(LLParcel::ECategory category);


#endif